Support for extern pointer for located variables + Preliminary slave code (broken)
authoretisserant
Mon, 23 Jun 2008 17:52:21 +0200
changeset 163 482ca562d414
parent 162 bf3eac08a96b
child 164 072e81cc65fe
Support for extern pointer for located variables + Preliminary slave code (broken)
plugins/canfestival/canfestival.py
plugins/canfestival/config_utils.py
--- a/plugins/canfestival/canfestival.py	Mon Jun 23 16:06:20 2008 +0200
+++ b/plugins/canfestival/canfestival.py	Mon Jun 23 17:52:21 2008 +0200
@@ -1,4 +1,4 @@
-import os, sys, wx
+import os, sys
 base_folder = os.path.split(sys.path[0])[0]
 CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
 sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
@@ -15,14 +15,18 @@
 from gnosis.xml.pickle.util import setParanoia
 setParanoia(0)
 
-class _NetworkEdit(networkedit):
-    " Overload some of CanFestival Network Editor methods "
+#--------------------------------------------------
+#                    SLAVE
+#--------------------------------------------------
+
+class _NodeEdit(objdictedit):
+    " Overload some of CanFestival Node Editor methods "
     def OnCloseFrame(self, event):
         " Do reset _NodeListPlug.View when closed"
         self._onclose()
         event.Skip()
 
-class _NodeListPlug(NodeList):
+class _SlavePlug(NodeManager):
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <xsd:element name="CanFestivalNode">
@@ -30,18 +34,30 @@
           <xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
           <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
           <xsd:attribute name="NodeId" type="xsd:string" use="required"/>
-          <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
         </xsd:complexType>
       </xsd:element>
     </xsd:schema>
     """
 
+    def GetSlaveODPath(self):
+        os.path.join(self.PlugPath(), 'slave.od')
+
     def __init__(self):
-        manager = NodeManager()
         # TODO change netname when name change
-        NodeList.__init__(self, manager, self.BaseParams.getName())
-        self.LoadProject(self.PlugPath())
-
+        NodeManager.__init__(self)
+        odfilepath = self.GetSlaveODPath()
+        if(os.path.isfile(odfilepath)):
+            self.OpenFileInCurrent(odfilepath)
+        else:
+            self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
+                               0x00,         # NodeID - will be changed at build time
+                               "slave",      # Type
+                               "",           # description 
+                               "None",       # profile
+                               "",           # prfile filepath
+                               "heartbeat",  # NMT
+                               [])           # options
+            
     _View = None
     def _OpenView(self, logger):
         if not self._View:
@@ -49,7 +65,7 @@
                 self._View = None
             def _onsave():
                 self.GetPlugRoot().SaveProject()
-            self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
+            self._View = _NodeEdit(self.GetPlugRoot().AppFrame, self)
             # TODO redefine BusId when IEC channel change
             self._View.SetBusId(self.GetCurrentLocation())
             self._View._onclose = _onclose
@@ -121,6 +137,117 @@
         file.close()
         
         return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+
+#--------------------------------------------------
+#                    MASTER
+#--------------------------------------------------
+
+class _NetworkEdit(networkedit):
+    " Overload some of CanFestival Network Editor methods "
+    def OnCloseFrame(self, event):
+        " Do reset _NodeListPlug.View when closed"
+        self._onclose()
+        event.Skip()
+
+class _NodeListPlug(NodeList):
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalNode">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
+          <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
+          <xsd:attribute name="NodeId" type="xsd:string" use="required"/>
+          <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
+
+    def __init__(self):
+        manager = NodeManager()
+        # TODO change netname when name change
+        NodeList.__init__(self, manager, self.BaseParams.getName())
+        self.LoadProject(self.PlugPath())
+
+    _View = None
+    def _OpenView(self, logger):
+        if not self._View:
+            def _onclose():
+                self._View = None
+            def _onsave():
+                self.GetPlugRoot().SaveProject()
+            self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
+            # TODO redefine BusId when IEC channel change
+            self._View.SetBusId(self.GetCurrentLocation())
+            self._View._onclose = _onclose
+            self._View._onsave = _onsave
+            self._View.Show()
+
+    def _ShowMasterGenerated(self, logger):
+        buildpath = self._getBuildPath()
+        # Eventually create build dir
+        if not os.path.exists(buildpath):
+            logger.write_error("Error: No PLC built\n")
+            return
+        
+        masterpath = os.path.join(buildpath, "MasterGenerated.od")
+        if not os.path.exists(masterpath):
+            logger.write_error("Error: No Master generated\n")
+            return
+        
+        new_dialog = objdictedit(None, [masterpath])
+        new_dialog.Show()
+
+    PluginMethods = [
+        {"bitmap" : os.path.join("images", "NetworkEdit"),
+         "name" : "Edit network", 
+         "tooltip" : "Edit CanOpen Network with NetworkEdit",
+         "method" : "_OpenView"},
+        {"name" : "Show Master", 
+         "tooltip" : "Show Master generated by config_utils",
+         "method" : "_ShowMasterGenerated"}
+    ]
+
+    def OnPlugClose(self):
+        if self._View:
+            self._View.Close()
+
+    def PlugTestModified(self):
+        return self.ChangesToSave or self.HasChanged()
+        
+    def OnPlugSave(self):
+        self.SetRoot(self.PlugPath())
+        self.SaveProject()
+        return True
+
+    def PlugGenerate_C(self, buildpath, locations, logger):
+        """
+        Generate C code
+        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        prefix = "_".join(map(lambda x:str(x), current_location))
+        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+        # Create a new copy of the model with DCF loaded with PDO mappings for desired location
+        master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
+        res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
+        if res :
+            raise Exception, res
+        
+        file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
+        dump(master, file)
+        file.close()
+        
+        return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
     
 class RootClass:
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -133,11 +260,11 @@
       </xsd:element>
     </xsd:schema>
     """
-    PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen node")]
+    PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
     def GetParamsAttributes(self, path = None):
         infos = PlugTemplate.GetParamsAttributes(self, path = None)
         for element in infos:
-            if element["name"] == "CanFestivalInstance":                         
+            if element["name"] == "CanFestivalInstance":
                 for child in element["children"]:
                     if child["name"] == "CAN_Driver":
                         DLL_LIST= getattr(canfestival_config,"DLL_LIST",None)
@@ -178,7 +305,7 @@
             format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
             format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
         
-        if wx.Platform == '__WXMSW__':
+        if sys.platform == 'win32':
             if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))):
                     format_dict["candriver"] += '_DEBUG.dll'
             else:
--- a/plugins/canfestival/config_utils.py	Mon Jun 23 16:06:20 2008 +0200
+++ b/plugins/canfestival/config_utils.py	Mon Jun 23 17:52:21 2008 +0200
@@ -138,6 +138,8 @@
         self.SlavesPdoNumber = {}
         # Dictionary of mapping value where unexpected variables are stored
         self.TrashVariables = {}
+        # Dictionary of pointed variables
+        self.PointedVariables = {}
         
         self.NodeList = nodelist
         self.Manager = self.NodeList.Manager
@@ -145,6 +147,8 @@
         self.MasterNode.SetNodeName(nodename)
         self.PrepareMasterNode()
 
+    def GetPointedVariables(self):
+        return self.PointedVariables
     
     def RemoveUsedNodeCobId(self, node):
         """
@@ -515,17 +519,18 @@
                                      VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
                                      variable_infos["nodeid"]
                     
+                    # Generate entry name
+                    indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
+                                                 variable_infos["sizelocation"],
+                                                 '_'.join(map(str,current_location)),
+                                                 variable_infos["nodeid"])    
+                    
                     # Search for an entry that has an empty subindex 
                     while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
                         # Entry doesn't exist
                         if not self.MasterNode.IsEntry(mapvariableidx):    
-                            # Generate entry name
-                            indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
-                                                     variable_infos["sizelocation"],
-                                                     '_'.join(map(str,current_location)),
-                                                     variable_infos["nodeid"])
                             # Add entry to MasterNode
-                            self.Manager.AddMapVariableToCurrent(mapvariableidx, indexname, 3, 1, self.MasterNode)
+                            self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
                             new_index = True
                             nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
                         else:
@@ -557,6 +562,9 @@
                         if typeinfos != None:
                             value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
                             self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
+                        
+                        # Add variable to pointed variables
+                        self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
 
 def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
     """
@@ -574,7 +582,7 @@
     
     dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
     dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
-    return dcfgenerator.GetMasterNode()
+    return dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
 
 if __name__ == "__main__":
     import os, sys, getopt