]> rtime.felk.cvut.cz Git - CanFestival-3.git/blobdiff - objdictgen/eds_utils.py
Modification for generating eds file from a node instead of a manager
[CanFestival-3.git] / objdictgen / eds_utils.py
index 6cbdd3a2d4c4d008a7fc84593a2c1a455bad7d0a..1a02bc82d9c0ef28f7e77383ccf6d523d6d994ef 100644 (file)
@@ -30,22 +30,24 @@ from time import *
 import os,re
 
 # Regular expression for finding index section names
-index_model = re.compile('([0-9A-F]{1,4})')
+index_model = re.compile('([0-9A-F]{1,4}$)')
 # Regular expression for finding subindex section names
-subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2})')
+subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2}$)')
+# Regular expression for finding index section names
+index_objectlinks_model = re.compile('([0-9A-F]{1,4}OBJECTLINKS$)')
 
 # Regular expression for finding NodeXPresent keynames
-nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT')
+nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT$')
 # Regular expression for finding NodeXName keynames
-nodename_model = re.compile('NODE([0-9]{1,3})NAME')
+nodename_model = re.compile('NODE([0-9]{1,3})NAME$')
 # Regular expression for finding NodeXDCFName keynames
-nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME')
+nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME$')
 
 # Dictionary for quickly translate boolean into integer value
 BOOL_TRANSLATE = {True : "1", False : "0"}
 
 # Dictionary for quickly translate eds access value into canfestival access value
-ACCESS_TRANSLATE = {"ro" : "ro", "wo" : "wo", "rw" : "rw", "rwr" : "rw", "rww" : "rw", "const" : "ro"}
+ACCESS_TRANSLATE = {"RO" : "ro", "WO" : "wo", "RW" : "rw", "RWR" : "rw", "RWW" : "rw", "CONST" : "ro"}
 
 # Function for verifying data values
 is_integer = lambda x: type(x) in (IntType, LongType)
@@ -56,14 +58,14 @@ is_boolean = lambda x: x in (0, 1)
 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, 
                     "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, 
                     "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer,
-                    "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"],
+                    "ACCESSTYPE" : lambda x: x.upper() in ACCESS_TRANSLATE.keys(),
                     "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean,
-                    "OBJFLAGS" : is_integer}
+                    "OBJFLAGS" : is_integer, "PARAMETERVALUE" : lambda x: True,}
 
 # Define entry parameters by entry ObjectType number
 ENTRY_TYPES = {7 : {"name" : " VAR",
                     "require" : ["PARAMETERNAME", "DATATYPE", "ACCESSTYPE"],
-                    "optional" : ["OBJECTTYPE", "DEFAULTVALUE", "PDOMAPPING", "LOWLIMIT", "HIGHLIMIT", "OBJFLAGS"]},
+                    "optional" : ["OBJECTTYPE", "DEFAULTVALUE", "PDOMAPPING", "LOWLIMIT", "HIGHLIMIT", "OBJFLAGS", "PARAMETERVALUE"]},
                8 : {"name" : "n ARRAY",
                     "require" : ["PARAMETERNAME", "OBJECTTYPE", "SUBNUMBER"],
                     "optional" : ["OBJFLAGS"]},
@@ -74,7 +76,7 @@ ENTRY_TYPES = {7 : {"name" : " VAR",
 
 # Function that search into Node Mappings the informations about an index or a subindex
 # and return the default value
-def GetDefaultValue(index, subIndex = None):
+def GetDefaultValue(Node, index, subIndex = None):
     infos = Node.GetEntryInfos(index)
     if infos["struct"] & node.OD_MultipleSubindexes:
         # First case entry is a record
@@ -110,7 +112,7 @@ def GetDefaultValue(index, subIndex = None):
 # an EDS file
 SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS", 
                     "MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS",
-                    "STANDARDDATATYPES"]
+                    "STANDARDDATATYPES", "SUPPORTEDMODULES"]
 
 
 # Function that extract sections from a file and returns a dictionary of the informations
@@ -154,15 +156,15 @@ def ParseCPJFile(filepath):
                         # value can be preceded and followed by whitespaces, so we escape them
                         value = value.strip()
                 
-                        # First case, value starts with "0x", then it's an hexadecimal value
-                        if value.startswith("0x"):
+                        # First case, value starts with "0x" or "-0x", then it's an hexadecimal value
+                        if value.startswith("0x") or value.startswith("-0x"):
                             try:
                                 computed_value = int(value, 16)
                             except:
                                 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
-                        elif value.isdigit():
-                            # Second case, value is a number and starts with "0", then it's an octal value
-                            if value.startswith("0"):
+                        elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
+                            # Second case, value is a number and starts with "0" or "-0", then it's an octal value
+                            if value.startswith("0") or value.startswith("-0"):
                                 computed_value = int(value, 8)
                             # Third case, value is a number and don't start with "0", then it's a decimal value
                             else:
@@ -249,6 +251,7 @@ def ParseEDSFile(filepath):
         # Search if the section name match an index or subindex expression
         index_result = index_model.match(section_name.upper())
         subindex_result = subindex_model.match(section_name.upper())
+        index_objectlinks_result = index_objectlinks_model.match(section_name.upper())
         
         # Compilation of the EDS information dictionary
         
@@ -260,20 +263,7 @@ def ParseEDSFile(filepath):
                 eds_dict[section_name.upper()] = values
             else:
                 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
-        # Second case, section name is a subindex name 
-        elif subindex_result:
-            # Extract index and subindex number
-            index, subindex = [int(value, 16) for value in subindex_result.groups()]
-            # If index hasn't been referenced before, we add an entry into the dictionary
-            # that will be updated later
-            if index not in eds_dict:
-                eds_dict[index] = {"subindexes" : {}}
-            if subindex not in eds_dict[index]["subindexes"]:
-                eds_dict[index]["subindexes"][subindex] = values
-            else:
-                raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
-            is_entry = True
-        # Third case, section name is an index name 
+        # Second case, section name is an index name 
         elif index_result:
             # Extract index number
             index = int(index_result.groups()[0], 16)
@@ -287,6 +277,22 @@ def ParseEDSFile(filepath):
             else:
                 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
             is_entry = True
+        # Third case, section name is a subindex name 
+        elif subindex_result:
+            # Extract index and subindex number
+            index, subindex = [int(value, 16) for value in subindex_result.groups()]
+            # If index hasn't been referenced before, we add an entry into the dictionary
+            # that will be updated later
+            if index not in eds_dict:
+                eds_dict[index] = {"subindexes" : {}}
+            if subindex not in eds_dict[index]["subindexes"]:
+                eds_dict[index]["subindexes"][subindex] = values
+            else:
+                raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
+            is_entry = True
+        # Third case, section name is a subindex name 
+        elif index_objectlinks_result:
+            pass
         # In any other case, there is a syntax problem into EDS file
         else:
             raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
@@ -313,14 +319,14 @@ def ParseEDSFile(filepath):
                         except:
                             raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
                     # Second case, value starts with "0x", then it's an hexadecimal value
-                    elif value.startswith("0x"):
+                    elif value.startswith("0x") or value.startswith("-0x"):
                         try:
                             computed_value = int(value, 16)
                         except:
                             raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
-                    elif value.isdigit():
+                    elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
                         # Third case, value is a number and starts with "0", then it's an octal value
-                        if value.startswith("0"):
+                        if value.startswith("0") or value.startswith("-0"):
                             computed_value = int(value, 8)
                         # Forth case, value is a number and don't start with "0", then it's a decimal value
                         else:
@@ -379,6 +385,20 @@ def ParseEDSFile(filepath):
                     attributes = "Attribute \"%s\" is"%unsupported[0]
                 raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"])
             
+            if "PARAMETERVALUE" in values:
+                try:
+                    if values["DATATYPE"] in (0x09, 0x0A, 0x0B, 0x0F):
+                        values["PARAMETERVALUE"] = str(values["PARAMETERVALUE"])
+                    elif values["DATATYPE"] in (0x08, 0x11):
+                        values["PARAMETERVALUE"] = float(values["PARAMETERVALUE"])
+                    elif values["DATATYPE"] == 0x01:
+                        values["PARAMETERVALUE"] = {0 : False, 1 : True}[values["PARAMETERVALUE"]]
+                    else:
+                        if type(values["PARAMETERVALUE"]) != IntType and values["PARAMETERVALUE"].find("$NODEID") == -1:
+                            raise
+                except:
+                    raise SyntaxError, "Error on section \"[%s]\":\nParameterValue incompatible with DataType"%section_name
+            
             if "DEFAULTVALUE" in values:
                 try:
                     if values["DATATYPE"] in (0x09, 0x0A, 0x0B, 0x0F):
@@ -407,17 +427,20 @@ def WriteFile(filepath, content):
 
 
 # Function that generate the EDS file content for the current node in the manager
-def GenerateFileContent(filepath):
+def GenerateFileContent(Node, filepath):
     # Dictionary of each index contents
     indexContents = {}
     
     # Extract local time
     current_time = localtime()
     # Extract node informations
-    nodename, nodeid, nodetype, description = Manager.GetCurrentNodeInfos()
+    nodename = Node.GetNodeName()
+    nodeid = Node.GetNodeID()
+    nodetype = Node.GetNodeType() 
+    description = Node.GetNodeDescription()
     
-    # Compiling lists of indexes defined
-    entries = [idx for name, idx in Manager.GetCurrentValidIndexes(0, 0xFFFF)]
+    # Retreiving lists of indexes defined
+    entries = Node.GetIndexes()
     
     # Generate FileInfo section
     fileContent = "[FileInfo]\n"
@@ -447,10 +470,10 @@ def GenerateFileContent(filepath):
     fileContent += "\n[DeviceInfo]\n"
     fileContent += "VendorName=CANFestival\n"
     # Use information typed by user in Identity entry
-    fileContent += "VendorNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 1)
+    fileContent += "VendorNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 1)
     fileContent += "ProductName=%s\n"%nodename
-    fileContent += "ProductNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 2)
-    fileContent += "RevisionNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 3)
+    fileContent += "ProductNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 2)
+    fileContent += "RevisionNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 3)
     # CANFestival support all baudrates as soon as driver choosen support them
     fileContent += "BaudRate_10=1\n"
     fileContent += "BaudRate_20=1\n"
@@ -496,20 +519,23 @@ def GenerateFileContent(filepath):
     # For each entry, we generate the entry section or sections if there is subindexes
     for entry in entries:
         # Extract infos and values for the entry
-        entry_infos = Manager.GetEntryInfos(entry)
-        values = Manager.GetCurrentEntry(entry, compute = False)
+        entry_infos = Node.GetEntryInfos(entry)
+        values = Node.GetEntry(entry, compute = False)
         # Define section name
         text = "\n[%X]\n"%entry
         # If there is only one value, it's a VAR entry
         if type(values) != ListType:
             # Extract the informations of the first subindex
-            subentry_infos = Manager.GetSubentryInfos(entry, 0)
+            subentry_infos = Node.GetSubentryInfos(entry, 0)
             # Generate EDS informations for the entry
             text += "ParameterName=%s\n"%subentry_infos["name"]
             text += "ObjectType=0x7\n"
             text += "DataType=0x%4.4X\n"%subentry_infos["type"]
             text += "AccessType=%s\n"%subentry_infos["access"]
-            text += "DefaultValue=%s\n"%values
+            if subentry_infos["type"] == 1:
+                text += "DefaultValue=%s\n"%BOOL_TRANSLATE[values]
+            else:
+                text += "DefaultValue=%s\n"%values
             text += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
         else:
             # Generate EDS informations for the entry
@@ -525,7 +551,7 @@ def GenerateFileContent(filepath):
             nb_subentry = 0
             for subentry, value in enumerate(values):
                 # Extract the informations of each subindex
-                subentry_infos = Manager.GetSubentryInfos(entry, subentry)
+                subentry_infos = Node.GetSubentryInfos(entry, subentry)
                 # If entry is not for the compatibility, generate informations for subindex
                 if subentry_infos["name"] != "Compatibility Entry":
                     subtext += "\n[%Xsub%X]\n"%(entry, subentry)
@@ -533,7 +559,10 @@ def GenerateFileContent(filepath):
                     subtext += "ObjectType=0x7\n"
                     subtext += "DataType=0x%4.4X\n"%subentry_infos["type"]
                     subtext += "AccessType=%s\n"%subentry_infos["access"]
-                    subtext += "DefaultValue=%s\n"%value
+                    if subentry_infos["type"] == 1:
+                        subtext += "DefaultValue=%s\n"%BOOL_TRANSLATE[value]
+                    else:
+                        subtext += "DefaultValue=%s\n"%value
                     subtext += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
                     # Increment number of subindex defined 
                     nb_subentry += 1
@@ -593,12 +622,10 @@ def GenerateFileContent(filepath):
 
 
 # Function that generates EDS file from current node edited
-def GenerateEDSFile(filepath, manager):
-    global Manager
-    Manager = manager
+def GenerateEDSFile(filepath, node):
     try:
         # Generate file content
-        content = GenerateFileContent(filepath)
+        content = GenerateFileContent(node, filepath)
         # Write file
         WriteFile(filepath, content)
         return None
@@ -624,7 +651,6 @@ def GenerateCPJContent(nodelist):
 
 # Function that generates Node from an EDS file
 def GenerateNode(filepath, nodeID = 0):
-    global Node
     # Create a new node
     Node = node.Node(id = nodeID)
     try:
@@ -665,15 +691,16 @@ def GenerateNode(filepath, nodeID = 0):
                         # Add mapping for first subindex
                         Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], 
                                                                  "type" : values["DATATYPE"], 
-                                                                 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], 
+                                                                 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"].upper()], 
                                                                  "pdo" : values.get("PDOMAPPING", 0) == 1})
-                    # Second case, entry is an ARRAY
-                    elif values["OBJECTTYPE"] == 8:
+                    # Second case, entry is an ARRAY or RECORD
+                    elif values["OBJECTTYPE"] in [8, 9]:
                         # Extract maximum subindex number defined
                         try:
                             max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
                         except:
-                            raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry
+                            max_subindex = max(*values["subindexes"].keys())
+                            #raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or RECORD entry"%entry
                         # Add mapping for entry
                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 3)
                         # Add mapping for first subindex
@@ -684,58 +711,68 @@ def GenerateNode(filepath, nodeID = 0):
                             if subindex in values["subindexes"]:
                                 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], 
                                                                                 "type" : values["subindexes"][subindex]["DATATYPE"], 
-                                                                                "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], 
+                                                                                "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"].upper()], 
                                                                                 "pdo" : values["subindexes"][subindex].get("PDOMAPPING", 0) == 1})
                             # if not, we add a mapping for compatibility 
                             else:
                                 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False})
-                    # Third case, entry is an RECORD
-                    elif values["OBJECTTYPE"] == 9:
-                        # Verify that the first subindex is defined
-                        if 0 not in values["subindexes"]:
-                            raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry
-                        # Add mapping for entry
-                        Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7)
-                        # Add mapping for first subindex
-                        Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
-                        # Verify that second subindex is defined
-                        if 1 in values:
-                            Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", 
-                                                                     "type" : values["subindexes"][1]["DATATYPE"], 
-                                                                     "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], 
-                                                                     "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1})
-                        else:
-                            raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
+##                    # Third case, entry is an RECORD
+##                    elif values["OBJECTTYPE"] == 9:
+##                        # Verify that the first subindex is defined
+##                        if 0 not in values["subindexes"]:
+##                            raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry
+##                        # Add mapping for entry
+##                        Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7)
+##                        # Add mapping for first subindex
+##                        Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
+##                        # Verify that second subindex is defined
+##                        if 1 in values["subindexes"]:
+##                            Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", 
+##                                                                     "type" : values["subindexes"][1]["DATATYPE"], 
+##                                                                     "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"].upper()], 
+##                                                                     "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1,
+##                                                                     "nbmax" : 0xFE})
+##                        else:
+##                            raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
                 
                 # Define entry for the new node
                 
                 # First case, entry is a VAR
                 if values["OBJECTTYPE"] == 7:
                     # Take default value if it is defined
-                    if "DEFAULTVALUE" in values:
+                    if "PARAMETERVALUE" in values:
+                        value = values["PARAMETERVALUE"]
+                    elif "DEFAULTVALUE" in values:
                         value = values["DEFAULTVALUE"]
                     # Find default value for value type of the entry
                     else:
-                        value = GetDefaultValue(entry)
+                        value = GetDefaultValue(Node, entry)
                     Node.AddEntry(entry, 0, value)
                 # Second case, entry is an ARRAY or a RECORD
                 elif values["OBJECTTYPE"] in (8, 9):
                     # Verify that "Subnumber" attribute is defined and has a valid value
                     if "SUBNUMBER" in values and values["SUBNUMBER"] > 0:
+                        consecutive = False
                         # Extract maximum subindex number defined
                         try:
                             max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
                         except:
-                            raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
+                            max_subindex = values["SUBNUMBER"] - 1
+                            consecutive = True
+                            #raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
                         Node.AddEntry(entry, value = [])
                         # Define value for all subindexes except the first 
                         for subindex in xrange(1, int(max_subindex) + 1):
                             # Take default value if it is defined and entry is defined
-                            if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]:
+                            if subindex in values["subindexes"] and "PARAMETERVALUE" in values["subindexes"][subindex]:
+                                value = values["subindexes"][subindex]["PARAMETERVALUE"]
+                            elif subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]:
                                 value = values["subindexes"][subindex]["DEFAULTVALUE"]
                             # Find default value for value type of the subindex
+                            elif subindex in values["subindexes"] or not consecutive:
+                                value = GetDefaultValue(Node, entry, subindex)
                             else:
-                                value = GetDefaultValue(entry, subindex)
+                                raise SyntaxError, "Error on entry 0x%4.4X:\nCan't recompose implemented subindexes in this ARRAY or RECORD entry"%entry
                             Node.AddEntry(entry, subindex, value)
                     else:
                         raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry