Adding support for MCL
authorlaurent
Wed, 22 Feb 2012 01:39:22 +0100
changeset 2034 ae8fecf082a1
parent 2033 1c64b84c0609
child 2035 1d113faf4433
Adding support for MCL
etherlab/ConfigEditor.py
etherlab/etherlab.py
etherlab/plc_ds402node.c
--- a/etherlab/ConfigEditor.py	Thu Feb 16 18:40:13 2012 +0100
+++ b/etherlab/ConfigEditor.py	Wed Feb 22 01:39:22 2012 +0100
@@ -145,20 +145,16 @@
                 grid.SetCellTextColour(row, col, highlight_colours[1])
             self.ResizeRow(grid, row)
 
-[ID_SLAVEPANEL, ID_SLAVEPANELTYPELABEL,
- ID_SLAVEPANELTYPE, ID_SLAVEPANELTYPEBROWSE, 
- ID_SLAVEPANELALIASLABEL, ID_SLAVEPANELALIAS, 
- ID_SLAVEPANELPOSLABEL, ID_SLAVEPANELPOS, 
- ID_SLAVEPANELSLAVEINFOSSTATICBOX, ID_SLAVEPANELVENDORLABEL, 
- ID_SLAVEPANELVENDOR, ID_SLAVEPANELPRODUCTCODELABEL, 
- ID_SLAVEPANELPRODUCTCODE, ID_SLAVEPANELREVISIONNUMBERLABEL, 
- ID_SLAVEPANELREVISIONNUMBER, ID_SLAVEPANELPHYSICSLABEL, 
- ID_SLAVEPANELPHYSICS, ID_SLAVEPANELSYNCMANAGERSLABEL, 
- ID_SLAVEPANELSYNCMANAGERSGRID, ID_SLAVEPANELVARIABLESLABEL, 
- ID_SLAVEPANELVARIABLESGRID, 
-] = [wx.NewId() for _init_ctrls in range(21)]
-
-class SlavePanel(wx.Panel):
+[ID_SLAVEINFOSPANEL, ID_SLAVEINFOSPANELVENDORLABEL, 
+ ID_SLAVEINFOSPANELVENDOR, ID_SLAVEINFOSPANELPRODUCTCODELABEL, 
+ ID_SLAVEINFOSPANELPRODUCTCODE, ID_SLAVEINFOSPANELREVISIONNUMBERLABEL, 
+ ID_SLAVEINFOSPANELREVISIONNUMBER, ID_SLAVEINFOSPANELPHYSICSLABEL, 
+ ID_SLAVEINFOSPANELPHYSICS, ID_SLAVEINFOSPANELSYNCMANAGERSLABEL, 
+ ID_SLAVEINFOSPANELSYNCMANAGERSGRID, ID_SLAVEINFOSPANELVARIABLESLABEL, 
+ ID_SLAVEINFOSPANELVARIABLESGRID, 
+] = [wx.NewId() for _init_ctrls in range(13)]
+
+class SlaveInfosPanel(wx.Panel):
     
     if wx.VERSION < (2, 6, 0):
         def Bind(self, event, function, id = None):
@@ -168,43 +164,14 @@
                 event(self, function)
     
     def _init_coll_MainSizer_Items(self, parent):
-        parent.AddSizer(self.PositionSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        parent.AddSizer(self.SlaveInfosBoxSizer, 0, border=5, flag=wx.GROW|wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT)
-    
+        parent.AddSizer(self.SlaveInfosDetailsSizer, 0, border=5, flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddWindow(self.SyncManagersLabel, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddWindow(self.SyncManagersGrid, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddWindow(self.VariablesLabel, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddWindow(self.VariablesGrid, 0, border=5, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.GROW)
+        
     def _init_coll_MainSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
-        parent.AddGrowableRow(1)
-    
-    def _init_coll_PositionSizer_Items(self, parent):
-        parent.AddWindow(self.TypeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        parent.AddSizer(self.TypeSizer, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.AliasLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        parent.AddWindow(self.Alias, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.PosLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        parent.AddWindow(self.Pos, 0, border=0, flag=wx.GROW)
-    
-    def _init_coll_PositionSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-        parent.AddGrowableCol(3)
-        parent.AddGrowableCol(5)
-        parent.AddGrowableRow(0)
-    
-    def _init_coll_TypeSizer_Items(self, parent):
-        parent.AddWindow(self.Type, 1, border=0, flag=0)
-        parent.AddWindow(self.TypeBrowse, 0, border=0, flag=0)
-    
-    def _init_coll_SlaveInfosBoxSizer_Items(self, parent):
-        parent.AddSizer(self.SlaveInfosSizer, 1, border=5, flag=wx.GROW|wx.ALL)
-    
-    def _init_coll_SlaveInfosSizer_Items(self, parent):
-        parent.AddSizer(self.SlaveInfosDetailsSizer, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.SyncManagersLabel, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.SyncManagersGrid, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.VariablesLabel, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
-        
-    def _init_coll_SlaveInfosSizer_Growables(self, parent):
-        parent.AddGrowableCol(0)
         parent.AddGrowableRow(2, 1)
         parent.AddGrowableRow(4, 2)
         
@@ -223,110 +190,65 @@
         parent.AddGrowableCol(3)
     
     def _init_sizers(self):
-        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
-        self.PositionSizer = wx.FlexGridSizer(cols=6, hgap=5, rows=1, vgap=0)
-        self.TypeSizer = wx.BoxSizer(wx.HORIZONTAL)
-        self.SlaveInfosBoxSizer = wx.StaticBoxSizer(self.SlaveInfosStaticBox, wx.VERTICAL)
-        self.SlaveInfosSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5)
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5)
         self.SlaveInfosDetailsSizer = wx.FlexGridSizer(cols=4, hgap=5, rows=2, vgap=5)
         
         self._init_coll_MainSizer_Growables(self.MainSizer)
         self._init_coll_MainSizer_Items(self.MainSizer)
-        self._init_coll_PositionSizer_Growables(self.PositionSizer)
-        self._init_coll_PositionSizer_Items(self.PositionSizer)
-        self._init_coll_TypeSizer_Items(self.TypeSizer)
-        self._init_coll_SlaveInfosBoxSizer_Items(self.SlaveInfosBoxSizer)
-        self._init_coll_SlaveInfosSizer_Growables(self.SlaveInfosSizer)
-        self._init_coll_SlaveInfosSizer_Items(self.SlaveInfosSizer)
         self._init_coll_SlaveInfosDetailsSizer_Growables(self.SlaveInfosDetailsSizer)
         self._init_coll_SlaveInfosDetailsSizer_Items(self.SlaveInfosDetailsSizer)
         
         self.SetSizer(self.MainSizer)
-    
+
     def _init_ctrls(self, prnt):
-        wx.Panel.__init__(self, id=ID_SLAVEPANEL, name='SlavePanel', parent=prnt,
+        wx.Panel.__init__(self, id=ID_SLAVEINFOSPANEL, name='SlavePanel', parent=prnt,
               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
         
-        self.TypeLabel = wx.StaticText(id=ID_SLAVEPANELTYPELABEL,
-              label=_('Type:'), name='TypeLabel', parent=self,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.Type = wx.TextCtrl(id=ID_SLAVEPANELTYPE, value='',
-              name='Type', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=wx.TE_READONLY)
-        
-        self.TypeBrowse = wx.Button(id=ID_SLAVEPANELTYPEBROWSE, label='...',
-              name='TypeBrowse', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(30, 24), style=0)
-        self.Bind(wx.EVT_BUTTON, self.OnTypeBrowseClick, id=ID_SLAVEPANELTYPEBROWSE)
-        
-        self.AliasLabel = wx.StaticText(id=ID_SLAVEPANELALIASLABEL,
-              label=_('Alias:'), name='AliasLabel', parent=self,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.Alias = wx.SpinCtrl(id=ID_SLAVEPANELALIAS,
-              name='Alias', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff)
-        self.Bind(wx.EVT_SPINCTRL, self.OnAliasChanged, id=ID_SLAVEPANELALIAS)
-        
-        self.PosLabel = wx.StaticText(id=ID_SLAVEPANELPOSLABEL,
-              label=_('Position:'), name='PositionLabel', parent=self,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.Pos = wx.SpinCtrl(id=ID_SLAVEPANELPOS,
-              name='Pos', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff)
-        self.Bind(wx.EVT_SPINCTRL, self.OnPositionChanged, id=ID_SLAVEPANELPOS)
-        
-        self.SlaveInfosStaticBox = wx.StaticBox(id=ID_SLAVEPANELSLAVEINFOSSTATICBOX,
-              label=_('Slave infos:'), name='SlaveInfosStaticBox', parent=self,
-              pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
-        
-        self.VendorLabel = wx.StaticText(id=ID_SLAVEPANELVENDORLABEL,
+        self.VendorLabel = wx.StaticText(id=ID_SLAVEINFOSPANELVENDORLABEL,
               label=_('Vendor:'), name='VendorLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.Vendor = wx.TextCtrl(id=ID_SLAVEPANELVENDOR, value='',
+        self.Vendor = wx.TextCtrl(id=ID_SLAVEINFOSPANELVENDOR, value='',
               name='Vendor', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(0, 24), style=wx.TE_READONLY)
         
-        self.ProductCodeLabel = wx.StaticText(id=ID_SLAVEPANELPRODUCTCODELABEL,
+        self.ProductCodeLabel = wx.StaticText(id=ID_SLAVEINFOSPANELPRODUCTCODELABEL,
               label=_('Product code:'), name='ProductCodeLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.ProductCode = wx.TextCtrl(id=ID_SLAVEPANELPRODUCTCODE, value='',
+        self.ProductCode = wx.TextCtrl(id=ID_SLAVEINFOSPANELPRODUCTCODE, value='',
               name='ProductCode', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(0, 24), style=wx.TE_READONLY)
         
-        self.RevisionNumberLabel = wx.StaticText(id=ID_SLAVEPANELREVISIONNUMBERLABEL,
+        self.RevisionNumberLabel = wx.StaticText(id=ID_SLAVEINFOSPANELREVISIONNUMBERLABEL,
               label=_('Revision number:'), name='RevisionNumberLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.RevisionNumber = wx.TextCtrl(id=ID_SLAVEPANELREVISIONNUMBER, value='',
+        self.RevisionNumber = wx.TextCtrl(id=ID_SLAVEINFOSPANELREVISIONNUMBER, value='',
               name='RevisionNumber', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(0, 24), style=wx.TE_READONLY)
         
-        self.PhysicsLabel = wx.StaticText(id=ID_SLAVEPANELPHYSICSLABEL,
+        self.PhysicsLabel = wx.StaticText(id=ID_SLAVEINFOSPANELPHYSICSLABEL,
               label=_('Physics:'), name='PhysicsLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.Physics = wx.TextCtrl(id=ID_SLAVEPANELPHYSICS, value='',
+        self.Physics = wx.TextCtrl(id=ID_SLAVEINFOSPANELPHYSICS, value='',
               name='Physics', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(0, 24), style=wx.TE_READONLY)
         
-        self.SyncManagersLabel =  wx.StaticText(id=ID_SLAVEPANELSYNCMANAGERSLABEL,
+        self.SyncManagersLabel =  wx.StaticText(id=ID_SLAVEINFOSPANELSYNCMANAGERSLABEL,
               label=_('Sync managers:'), name='SyncManagersLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.SyncManagersGrid = CustomGrid(id=ID_SLAVEPANELSYNCMANAGERSGRID,
+        self.SyncManagersGrid = CustomGrid(id=ID_SLAVEINFOSPANELSYNCMANAGERSGRID,
               name='SyncManagersGrid', parent=self, pos=wx.Point(0, 0), 
               size=wx.Size(0, 0), style=wx.VSCROLL)
         
-        self.VariablesLabel =  wx.StaticText(id=ID_SLAVEPANELVARIABLESLABEL,
+        self.VariablesLabel =  wx.StaticText(id=ID_SLAVEINFOSPANELVARIABLESLABEL,
               label=_('Variable entries:'), name='VariablesLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         
-        self.VariablesGrid = CustomGrid(id=ID_SLAVEPANELVARIABLESGRID,
+        self.VariablesGrid = CustomGrid(id=ID_SLAVEINFOSPANELVARIABLESGRID,
               name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
               size=wx.Size(0, 0), style=wx.VSCROLL)
         if wx.VERSION >= (2, 5, 0):
@@ -335,13 +257,11 @@
             wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
         
         self._init_sizers()
-    
-    def __init__(self, parent, controler, window, slave):
+        
+    def __init__(self, parent, controler):
         self._init_ctrls(parent)
         
         self.Controler = controler
-        self.ParentWindow = window
-        self.Slave = slave
         
         self.SyncManagersTable = SyncManagersTable(self, [], GetSyncManagersTableColnames())
         self.SyncManagersGrid.SetTable(self.SyncManagersTable)
@@ -369,27 +289,9 @@
             self.VariablesGrid.SetColAttr(col, attr)
             self.VariablesGrid.SetColMinimalWidth(col, self.VariablesGridColSizes[col])
             self.VariablesGrid.AutoSizeColumn(col, False)
-        
-        self.RefreshView()
-    
-    def GetSlaveTitle(self):
-        type_infos = self.Controler.GetSlaveType(self.Slave)
-        return "%s (%d:%d)" % (type_infos["device_type"], self.Slave[0], self.Slave[1])
-    
-    def GetSlave(self):
-        return self.Slave
-    
-    def SetSlave(self, slave):
-        if self.Slave != slave:
-            self.Slave = slave
-            self.RefreshView()
-
-    def RefreshView(self):
-        self.Alias.SetValue(self.Slave[0])
-        self.Pos.SetValue(self.Slave[1])
-        slave_infos = self.Controler.GetSlaveInfos(self.Slave)
+    
+    def SetSlaveInfos(self, slave_infos):
         if slave_infos is not None:
-            self.Type.SetValue(slave_infos["device_type"])
             self.Vendor.SetValue(slave_infos["vendor"])
             self.ProductCode.SetValue(slave_infos["product_code"])
             self.RevisionNumber.SetValue(slave_infos["revision_number"])
@@ -399,49 +301,14 @@
             self.VariablesTable.SetData(slave_infos["entries"])
             self.VariablesTable.ResetView(self.VariablesGrid)
         else:
-            type_infos = self.Controler.GetSlaveType(self.Slave)
-            self.Type.SetValue(type_infos["device_type"])
-        
-    def OnAliasChanged(self, event):
-        alias = self.Alias.GetValue()
-        if alias != self.Slave[0]:
-            result = self.Controler.SetSlavePos(self.Slave[:2], alias = alias)
-            if result is not None:
-                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
-                message.ShowModal()
-                message.Destroy()
-            else:
-                wx.CallAfter(self.ParentWindow.RefreshView, (alias, self.Slave[1]))
-                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
-        event.Skip()
-        
-    def OnPositionChanged(self, event):
-        position = self.Pos.GetValue()
-        if position != self.Slave[1]:
-            result = self.Controler.SetSlavePos(self.Slave, position = position)
-            if result is not None:
-                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
-                message.ShowModal()
-                message.Destroy()
-            else:
-                wx.CallAfter(self.ParentWindow.RefreshView, (self.Slave[0], position))
-                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
-        event.Skip()
-
-    def OnTypeBrowseClick(self, event):
-        dialog = SlaveTypeChoiceDialog(self, self.Controler, self.Controler.GetSlaveType(self.Slave))
-        if dialog.ShowModal() == wx.ID_OK:
-            result = self.Controler.SetSlaveType(self.Slave, dialog.GetType())
-            if result is not None:
-                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
-                message.ShowModal()
-                message.Destroy()
-            else:
-                wx.CallAfter(self.RefreshView)
-                wx.CallAfter(self.ParentWindow.RefreshSlaveNodesTitles)
-                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
-        dialog.Destroy()
-        event.Skip()
+            self.Vendor.SetValue("")
+            self.ProductCode.SetValue("")
+            self.RevisionNumber.SetValue("")
+            self.Physics.SetValue("")
+            self.SyncManagersTable.SetData([])
+            self.SyncManagersTable.ResetView(self.SyncManagersGrid)
+            self.VariablesTable.SetData([])
+            self.VariablesTable.ResetView(self.VariablesGrid)
 
     def OnVariablesGridCellLeftClick(self, event):
         row = event.GetRow()
@@ -468,9 +335,184 @@
         
         event.Skip()
 
-[ID_CONFIGEDITOR, ID_CONFIGEDITORADDSLAVEBUTTON,
- ID_CONFIGEDITORDELETESLAVEBUTTON, ID_CONFIGEDITORSLAVENODES,
-] = [wx.NewId() for _init_ctrls in range(4)]
+[ID_SLAVEPANEL, ID_SLAVEPANELTYPELABEL,
+ ID_SLAVEPANELTYPE, ID_SLAVEPANELTYPEBROWSE, 
+ ID_SLAVEPANELALIASLABEL, ID_SLAVEPANELALIAS, 
+ ID_SLAVEPANELPOSLABEL, ID_SLAVEPANELPOS, 
+ ID_SLAVEPANELSLAVEINFOSSTATICBOX, 
+] = [wx.NewId() for _init_ctrls in range(9)]
+
+class SlavePanel(wx.Panel):
+    
+    if wx.VERSION < (2, 6, 0):
+        def Bind(self, event, function, id = None):
+            if id is not None:
+                event(self, id, function)
+            else:
+                event(self, function)
+    
+    def _init_coll_MainSizer_Items(self, parent):
+        parent.AddSizer(self.PositionSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
+        parent.AddSizer(self.SlaveInfosBoxSizer, 0, border=5, flag=wx.GROW|wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT)
+    
+    def _init_coll_MainSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(1)
+    
+    def _init_coll_PositionSizer_Items(self, parent):
+        parent.AddWindow(self.TypeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
+        parent.AddSizer(self.TypeSizer, 0, border=0, flag=wx.GROW)
+        parent.AddWindow(self.AliasLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
+        parent.AddWindow(self.Alias, 0, border=0, flag=wx.GROW)
+        parent.AddWindow(self.PosLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
+        parent.AddWindow(self.Pos, 0, border=0, flag=wx.GROW)
+    
+    def _init_coll_PositionSizer_Growables(self, parent):
+        parent.AddGrowableCol(1)
+        parent.AddGrowableCol(3)
+        parent.AddGrowableCol(5)
+        parent.AddGrowableRow(0)
+    
+    def _init_coll_TypeSizer_Items(self, parent):
+        parent.AddWindow(self.Type, 1, border=0, flag=0)
+        parent.AddWindow(self.TypeBrowse, 0, border=0, flag=0)
+    
+    def _init_coll_SlaveInfosBoxSizer_Items(self, parent):
+        parent.AddWindow(self.SlaveInfosPanel, 1, border=0, flag=wx.GROW)
+    
+    def _init_sizers(self):
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
+        self.PositionSizer = wx.FlexGridSizer(cols=6, hgap=5, rows=1, vgap=0)
+        self.TypeSizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.SlaveInfosBoxSizer = wx.StaticBoxSizer(self.SlaveInfosStaticBox, wx.VERTICAL)
+        
+        self._init_coll_MainSizer_Growables(self.MainSizer)
+        self._init_coll_MainSizer_Items(self.MainSizer)
+        self._init_coll_PositionSizer_Growables(self.PositionSizer)
+        self._init_coll_PositionSizer_Items(self.PositionSizer)
+        self._init_coll_TypeSizer_Items(self.TypeSizer)
+        self._init_coll_SlaveInfosBoxSizer_Items(self.SlaveInfosBoxSizer)
+        
+        self.SetSizer(self.MainSizer)
+    
+    def _init_ctrls(self, prnt):
+        wx.Panel.__init__(self, id=ID_SLAVEPANEL, name='SlavePanel', parent=prnt,
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        
+        self.TypeLabel = wx.StaticText(id=ID_SLAVEPANELTYPELABEL,
+              label=_('Type:'), name='TypeLabel', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        
+        self.Type = wx.TextCtrl(id=ID_SLAVEPANELTYPE, value='',
+              name='Type', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(0, 24), style=wx.TE_READONLY)
+        
+        self.TypeBrowse = wx.Button(id=ID_SLAVEPANELTYPEBROWSE, label='...',
+              name='TypeBrowse', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(30, 24), style=0)
+        self.Bind(wx.EVT_BUTTON, self.OnTypeBrowseClick, id=ID_SLAVEPANELTYPEBROWSE)
+        
+        self.AliasLabel = wx.StaticText(id=ID_SLAVEPANELALIASLABEL,
+              label=_('Alias:'), name='AliasLabel', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        
+        self.Alias = wx.SpinCtrl(id=ID_SLAVEPANELALIAS,
+              name='Alias', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff)
+        self.Bind(wx.EVT_SPINCTRL, self.OnAliasChanged, id=ID_SLAVEPANELALIAS)
+        
+        self.PosLabel = wx.StaticText(id=ID_SLAVEPANELPOSLABEL,
+              label=_('Position:'), name='PositionLabel', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        
+        self.Pos = wx.SpinCtrl(id=ID_SLAVEPANELPOS,
+              name='Pos', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(0, 24), style=wx.SP_ARROW_KEYS, min=0, max=0xffff)
+        self.Bind(wx.EVT_SPINCTRL, self.OnPositionChanged, id=ID_SLAVEPANELPOS)
+        
+        self.SlaveInfosStaticBox = wx.StaticBox(id=ID_SLAVEPANELSLAVEINFOSSTATICBOX,
+              label=_('Slave infos:'), name='SlaveInfosStaticBox', parent=self,
+              pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
+        
+        self.SlaveInfosPanel = SlaveInfosPanel(self, self.Controler)
+        
+        self._init_sizers()
+    
+    def __init__(self, parent, controler, window, slave):
+        self.Controler = controler
+        self.ParentWindow = window
+        self.Slave = slave
+        
+        self._init_ctrls(parent)
+        
+        self.RefreshView()
+    
+    def GetSlaveTitle(self):
+        type_infos = self.Controler.GetSlaveType(self.Slave)
+        return "%s (%d:%d)" % (type_infos["device_type"], self.Slave[0], self.Slave[1])
+    
+    def GetSlave(self):
+        return self.Slave
+    
+    def SetSlave(self, slave):
+        if self.Slave != slave:
+            self.Slave = slave
+            self.RefreshView()
+
+    def RefreshView(self):
+        self.Alias.SetValue(self.Slave[0])
+        self.Pos.SetValue(self.Slave[1])
+        slave_infos = self.Controler.GetSlaveInfos(self.Slave)
+        if slave_infos is not None:
+            self.Type.SetValue(slave_infos["device_type"])
+        else:
+            type_infos = self.Controler.GetSlaveType(self.Slave)
+            self.Type.SetValue(type_infos["device_type"])
+        self.SlaveInfosPanel.SetSlaveInfos(slave_infos)
+        
+    def OnAliasChanged(self, event):
+        alias = self.Alias.GetValue()
+        if alias != self.Slave[0]:
+            result = self.Controler.SetSlavePos(self.Slave[:2], alias = alias)
+            if result is not None:
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
+                message.ShowModal()
+                message.Destroy()
+            else:
+                wx.CallAfter(self.ParentWindow.RefreshView, (alias, self.Slave[1]))
+                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
+        event.Skip()
+        
+    def OnPositionChanged(self, event):
+        position = self.Pos.GetValue()
+        if position != self.Slave[1]:
+            result = self.Controler.SetSlavePos(self.Slave, position = position)
+            if result is not None:
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
+                message.ShowModal()
+                message.Destroy()
+            else:
+                wx.CallAfter(self.ParentWindow.RefreshView, (self.Slave[0], position))
+                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
+        event.Skip()
+
+    def OnTypeBrowseClick(self, event):
+        dialog = SlaveTypeChoiceDialog(self, self.Controler, self.Controler.GetSlaveType(self.Slave))
+        if dialog.ShowModal() == wx.ID_OK:
+            result = self.Controler.SetSlaveType(self.Slave, dialog.GetType())
+            if result is not None:
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
+                message.ShowModal()
+                message.Destroy()
+            else:
+                wx.CallAfter(self.RefreshView)
+                wx.CallAfter(self.ParentWindow.RefreshSlaveNodesTitles)
+                wx.CallAfter(self.ParentWindow.RefreshParentWindow)
+        dialog.Destroy()
+        event.Skip()
+
+[ID_CONFIGEDITOR, ID_CONFIGEDITORSLAVENODES,
+] = [wx.NewId() for _init_ctrls in range(2)]
 
 [ID_CONFIGEDITORPLUGINMENUADDSLAVE, ID_CONFIGEDITORPLUGINMENUDELETESLAVE,
 ] = [wx.NewId() for _init_coll_PluginMenu_Items in range(2)]
@@ -586,4 +628,33 @@
             if self.Controler.RemoveSlave(panel.GetSlave()[:2]):
                 self.RefreshParentWindow()
                 wx.CallAfter(self.RefreshView)
-            
\ No newline at end of file
+
+
+[ID_DS402NODEEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+class DS402NodeEditor(EditorPanel):
+    
+    ID = ID_DS402NODEEDITOR
+    
+    def _init_Editor(self, prnt):
+        self.Editor = SlaveInfosPanel(prnt, self.Controler)
+        
+    def __init__(self, parent, controler, window):
+        EditorPanel.__init__(self, parent, "", window, controler)
+        
+        img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+    
+    def __del__(self):
+        self.Controler.OnCloseEditor(self)
+    
+    def GetTitle(self):
+        return self.Controler.PlugFullName()
+    
+    def GetBufferState(self):
+        return False, False
+        
+    def RefreshView(self):
+        self.Editor.SetSlaveInfos(self.Controler.GetSlaveInfos())
+        
\ No newline at end of file
--- a/etherlab/etherlab.py	Thu Feb 16 18:40:13 2012 +0100
+++ b/etherlab/etherlab.py	Wed Feb 22 01:39:22 2012 +0100
@@ -7,7 +7,7 @@
 from xmlclass import *
 from plugger import PlugTemplate
 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-from ConfigEditor import ConfigEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
+from ConfigEditor import ConfigEditor, DS402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
 
 #--------------------------------------------------
 #                 Ethercat DS402 Node
@@ -15,8 +15,10 @@
 
 NODE_VARIABLES = [
     ("ControlWord", 0x6040, 0x00, "UINT", "Q"),
+    ("TargetPosition", 0x607a, 0x00, "DINT", "Q"),
     ("StatusWord", 0x6041, 0x00, "UINT", "I"),
     ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"),
+    ("ActualPosition", 0x6064, 0x00, "DINT", "I"),
     ("ErrorCode", 0x603f, 0x00, "UINT", "I"),
 ]
 
@@ -30,6 +32,13 @@
       </xsd:element>
     </xsd:schema>
     """
+    EditorType = DS402NodeEditor
+    
+    def ExtractHexDecValue(self, value):
+        return ExtractHexDecValue(value)
+
+    def GetSizeOfType(self, type):
+        return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
     
     def _GetChildBySomething(self, something, toks):
         return self
@@ -57,7 +66,7 @@
         """
         return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(), 0)
 
-    def GetSlaveInfos(self):
+    def GetSlaveTypeInfos(self):
         slave_type = self.EtherlabDS402Slave.getNode_Type()
         
         for module_type, vendor_id, product_code, revision_number in self.PlugParent.GetModulesByProfile(402):
@@ -69,17 +78,40 @@
         
         return None
 
+    def GetSlaveInfos(self):
+        slave_typeinfos = self.GetSlaveTypeInfos()
+        if slave_typeinfos is not None:
+            device = self.PlugParent.GetModuleInfos(slave_typeinfos)
+            if device is not None:
+                infos = slave_typeinfos.copy()
+                entries = device.GetEntriesList()
+                entries_list = entries.items()
+                entries_list.sort()
+                infos.update({"physics": device.getPhysics(),
+                              "sync_managers": device.GetSyncManagers(),
+                              "entries": [entry[1] for entry in entries_list]})
+                return infos
+        return None
+
     def GetVariableLocationTree(self):
-        slave_infos = self.GetSlaveInfos()
+        slave_typeinfos = self.GetSlaveTypeInfos()
         vars = []
-        if slave_infos is not None:
-            vars = self.PlugParent.GetDeviceLocationTree(self.GetCurrentLocation(), slave_infos) 
+        if slave_typeinfos is not None:
+            vars = self.PlugParent.GetDeviceLocationTree(self.GetCurrentLocation(), slave_typeinfos) 
 
         return  {"name": self.BaseParams.getName(),
                  "type": LOCATION_PLUGIN,
                  "location": self.GetFullIEC_Channel(),
                  "children": vars}
 
+    PluginMethods = [
+        {"bitmap" : os.path.join("images", "EditCfile"),
+         "name" : _("Edit Node"), 
+         "tooltip" : _("Edit Node"),
+         "method" : "_OpenView"},
+    ]
+
+
     def PlugGenerate_C(self, buildpath, locations):
         """
         Generate C code
@@ -99,65 +131,53 @@
         
         slave_pos = current_location[-2:]
         
-        slave_infos = self.GetSlaveInfos()
+        slave_typeinfos = self.GetSlaveTypeInfos()
         device = None
-        if slave_infos is not None:
-            device = self.PlugParent.GetModuleInfos(slave_infos)
+        if slave_typeinfos is not None:
+            device = self.PlugParent.GetModuleInfos(slave_typeinfos)
         
         if device is None:
             raise (ValueError, 
                    _("No information found for DS402 node \"%s\" at location %s!") % (
-                      slave_infos["device_type"], ".".join(current_location)))
+                      slave_typeinfos["device_type"], ".".join(current_location)))
             
-        slave_idx = self.PlugParent.FileGenerator.DeclareSlave(slave_pos, slave_infos)
+        self.PlugParent.FileGenerator.DeclareSlave(slave_pos, slave_typeinfos)
         
         plc_ds402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_ds402node.c")
         plc_ds402node_file = open(plc_ds402node_filepath, 'r')
         plc_ds402node_code = plc_ds402node_file.read()
         plc_ds402node_file.close()
         
+        from plugins.motion import Headers
+        
         str_completion = {
             "location": location_str,
-            "MCL_includes": "",
-            "located_variables_declaration": [],
+            "MCL_headers": Headers,
+            "extern_located_variables_declaration": [],
             "entry_variables": [],
-            "extern_pdo_entry_configuration": [],
-            "retrieve_variables": [],
-            "publish_variables": [],
+            "init_entry_variables": [],
         }
         
-        variables = {}
         for variable in NODE_VARIABLES:
             var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable))
             var_infos["location"] = location_str
-            var_infos["slave"] = slave_idx
             var_infos["var_size"] = self.PlugParent.GetSizeOfType(var_infos["var_type"])
             var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos
-            var_infos["real_var"] = "__DS402Node_%(location)s.%(name)s" % var_infos
-            var_infos.update(slave_infos)
             
-            variables[(var_infos["index"], var_infos["subindex"])] = var_infos["name"]
-            
-            str_completion["entry_variables"].append("    IEC_%(var_type)s %(name)s;" % var_infos)
-            
-            ConfigureVariable(var_infos, str_completion)
-            
-            str_completion["extern_pdo_entry_configuration"].append(
-                "extern unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % var_infos)
-                
-            if var_infos["var_type"] == "BOOL":
-                str_completion["extern_pdo_entry_configuration"].append(
-                    "extern unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % var_infos)
+            str_completion["extern_located_variables_declaration"].append(
+                    "IEC_%(var_type)s *%(var_name)s;" % var_infos)
+            str_completion["entry_variables"].append(
+                    "    IEC_%(var_type)s *%(name)s;" % var_infos)
+            str_completion["init_entry_variables"].append(
+                    "    __DS402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos)
             
             self.PlugParent.FileGenerator.DeclareVariable(
                     slave_pos, var_infos["index"], var_infos["subindex"], 
-                    var_infos["var_type"], var_infos["dir"], var_infos["var_name"], False)
-        
-        for element in ["located_variables_declaration", 
+                    var_infos["var_type"], var_infos["dir"], var_infos["var_name"])
+        
+        for element in ["extern_located_variables_declaration", 
                         "entry_variables", 
-                        "extern_pdo_entry_configuration", 
-                        "retrieve_variables", 
-                        "publish_variables"]:
+                        "init_entry_variables"]:
             str_completion[element] = "\n".join(str_completion[element])
         
         Gen_DS402Nodefile_path = os.path.join(buildpath, "ds402node_%s.c"%location_str)
@@ -165,12 +185,6 @@
         ds402nodefile.write(plc_ds402node_code % str_completion)
         ds402nodefile.close()
         
-        for location in locations:
-            loc = location["LOC"][len(current_location):]
-            if variables.get(loc, None) is None:
-                self.PlugParent.FileGenerator.DeclareVariable(
-                    slave_pos, loc[0], loc[1], location["IEC_TYPE"], location["DIR"], location["NAME"])
-        
         return [(Gen_DS402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True
         
 
@@ -598,14 +612,23 @@
     if entry_infos["data_type"] is None:
         raise ValueError, _("Type of location \"%s\" not yet supported!") % entry_infos["var_name"]
 
-    if not entry_infos.has_key("real_var"):
-        entry_infos["real_var"] = "beremiz" + entry_infos["var_name"]
-        str_completion["located_variables_declaration"].append(
-            "IEC_%(var_type)s %(real_var)s;" % entry_infos)
-    str_completion["located_variables_declaration"].append(
-         "IEC_%(var_type)s *%(var_name)s = &%(real_var)s;" % entry_infos)
+    entry_infos["real_var"] = "beremiz" + entry_infos["var_name"]
+    str_completion["located_variables_declaration"].extend(
+        ["IEC_%(var_type)s %(real_var)s;" % entry_infos,
+         "IEC_%(var_type)s *%(var_name)s = &%(real_var)s;" % entry_infos])
+    
+    str_completion["used_pdo_entry_offset_variables_declaration"].append(
+        "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos)
     
     if entry_infos["data_type"] == "BIT":
+        str_completion["used_pdo_entry_offset_variables_declaration"].append(
+            "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos)
+        
+        str_completion["used_pdo_entry_configuration"].append(
+             ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + 
+              "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + 
+              "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos)
+        
         if entry_infos["dir"] == "I":
             str_completion["retrieve_variables"].append(
               ("    %(real_var)s = EC_READ_BIT(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
@@ -616,6 +639,10 @@
                "slave%(slave)d_%(index).4x_%(subindex).2x_bit, %(real_var)s);") % entry_infos)
     
     else:
+        str_completion["used_pdo_entry_configuration"].append(
+            ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + 
+             "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos)
+        
         if entry_infos["dir"] == "I":
             str_completion["retrieve_variables"].append(
                 ("    %(real_var)s = EC_READ_%(data_type)s(domain1_pd + " + 
@@ -625,25 +652,6 @@
                 ("    EC_WRITE_%(data_type)s(domain1_pd + slave%(slave)d_%(index).4x_%(subindex).2x, " + 
                  "%(real_var)s);") % entry_infos)
 
-def ConfigurePDO(entry_infos, str_completion):
-    str_completion["used_pdo_entry_offset_variables_declaration"].append(
-        "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x;" % entry_infos)
-        
-    if entry_infos["var_type"] == "BOOL":
-        str_completion["used_pdo_entry_offset_variables_declaration"].append(
-            "unsigned int slave%(slave)d_%(index).4x_%(subindex).2x_bit;" % entry_infos)
-        
-        str_completion["used_pdo_entry_configuration"].append(
-             ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, " + 
-              "0x%(index).4x, %(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x, " + 
-              "&slave%(slave)d_%(index).4x_%(subindex).2x_bit},") % entry_infos)
-        
-    else:
-        
-        str_completion["used_pdo_entry_configuration"].append(
-            ("    {%(alias)d, %(position)d, 0x%(vendor).8x, 0x%(product_code).8x, 0x%(index).4x, " + 
-             "%(subindex)d, &slave%(slave)d_%(index).4x_%(subindex).2x},") % entry_infos)
-
 class _EthercatCFileGenerator:
     
     def __init__(self, controler):
@@ -660,14 +668,13 @@
         self.Slaves.sort()
         return self.Slaves.index((slave_identifier, slave))
 
-    def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name, configure=True):
+    def DeclareVariable(self, slave_identifier, index, subindex, iec_type, dir, name):
         slave_variables = self.UsedVariables.setdefault(slave_identifier, {})
         
         entry_infos = slave_variables.get((index, subindex), None)
         if entry_infos is None:
             slave_variables[(index, subindex)] = {
                 "infos": (iec_type, dir, name),
-                "configure": configure,
                 "mapped": False}
         elif entry_infos["infos"] != (iec_type, dir, name):
             raise ValueError, _("Definition conflict for location \"%s\"") % name 
@@ -764,6 +771,7 @@
                         sync_managers.append(sync_manager_infos)
                     
                     pdos_index = []
+                    excluded_pdos = []
                     for only_mandatory in [True, False]:
                         for pdo, pdo_type in ([(pdo, "Inputs") for pdo in device.getTxPdo()] +
                                               [(pdo, "Outputs") for pdo in device.getRxPdo()]):
@@ -777,6 +785,9 @@
                             
                             pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent())
                             pdos_index.append(pdo_index)
+                            if pdo_index in excluded_pdos:
+                                continue
+                            
                             entries_infos = []
                             
                             for entry in entries:
@@ -805,11 +816,14 @@
                                         entry_infos["dir"] == "Q" and pdo_type != "Outputs"):
                                         raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
                                     
-                                    if entry_declaration["configure"]:
-                                        ConfigureVariable(entry_infos, str_completion)
-                                    ConfigurePDO(entry_infos, str_completion)
-                            
+                                    ConfigureVariable(entry_infos, str_completion)
+                                    
                             if pdo_needed:
+                                for excluded in pdo.getExclude():
+                                    excluded_index = ExtractHexDecValue(excluded.getcontent())
+                                    if excluded_index not in excluded_pdos:
+                                        excluded_pdos.append(excluded_index)
+                                
                                 sm = pdo.getSm()
                                 if sm is None:
                                     for sm_idx, sync_manager in enumerate(sync_managers):
@@ -874,9 +888,7 @@
                             if not dynamic_pdos.has_key(pdo_type):
                                 raise ValueError, _("No Sync manager defined for %s!") % pdo_type
                             
-                            if entry_declaration["configure"]:
-                                ConfigureVariable(entry_infos, str_completion)
-                            ConfigurePDO(entry_infos, str_completion)
+                            ConfigureVariable(entry_infos, str_completion)
                             
                             if len(dynamic_pdos[pdo_type]["pdos"]) > 0:
                                 pdo = dynamic_pdos[pdo_type]["pdos"][0]
--- a/etherlab/plc_ds402node.c	Thu Feb 16 18:40:13 2012 +0100
+++ b/etherlab/plc_ds402node.c	Wed Feb 22 01:39:22 2012 +0100
@@ -11,10 +11,14 @@
   #include "iec_std_lib.h"
 #endif
 
-%(MCL_includes)s
+IEC_INT beremiz__IW%(location)s_0;
+IEC_INT *__IW%(location)s_0 = &beremiz__IW%(location)s_0;
+
+%(MCL_headers)s
 
 IEC_UINT __InactiveMask = 0x4f;
 IEC_UINT __ActiveMask = 0x6f;
+IEC_UINT __PowerMask = 0x10;
 
 typedef enum {
 	__Unknown,
@@ -31,17 +35,17 @@
 typedef struct {
 %(entry_variables)s
 	__DS402NodeState state;
+	axis_s* axis;
 } __DS402Node;
 
 static __DS402Node __DS402Node_%(location)s;
 
-%(located_variables_declaration)s
-
-extern uint8_t *domain1_pd;
-%(extern_pdo_entry_configuration)s
+%(extern_located_variables_declaration)s
 
 int __init_%(location)s()
 {
+%(init_entry_variables)s;
+*__IW%(location)s_0 = __MK_AllocAxis(&(__DS402Node_%(location)s.axis));
 	return 0;
 }
 
@@ -51,11 +55,8 @@
 
 void __retrieve_%(location)s()
 {
-	IEC_UINT statusword_inactive = __DS402Node_%(location)s.StatusWord & __InactiveMask;
-	IEC_UINT statusword_active = __DS402Node_%(location)s.StatusWord & __ActiveMask;
-
-    // DS402 input entries extraction
-%(retrieve_variables)s
+	IEC_UINT statusword_inactive = *(__DS402Node_%(location)s.StatusWord) & __InactiveMask;
+	IEC_UINT statusword_active = *(__DS402Node_%(location)s.StatusWord) & __ActiveMask;
 
 	// DS402 node state computation
 	__DS402Node_%(location)s.state = __Unknown;
@@ -95,35 +96,40 @@
 		return;
 	}
 
+	__DS402Node_%(location)s.axis->PowerFeedback = __DS402Node_%(location)s.state != __OperationEnabled;
+	__DS402Node_%(location)s.axis->ActualPosition = (IEC_REAL)(*(__DS402Node_%(location)s.ActualPosition)) * __DS402Node_%(location)s.axis->RatioDenominator / __DS402Node_%(location)s.axis->RatioNumerator;
+
+	__MK_UpdateAxis(*__IW%(location)s_0);
 }
 
 void __publish_%(location)s()
 {
+	__MK_ComputeAxis(*__IW%(location)s_0);
+
+	IEC_BOOL power = ((*(__DS402Node_%(location)s.StatusWord) & __PowerMask) > 0) && __DS402Node_%(location)s.axis->Power;
+
 	// DS402 node state transition computation
 	switch (__DS402Node_%(location)s.state) {
 	    case __SwitchOnDisabled:
-	    	__DS402Node_%(location)s.ControlWord = (__DS402Node_%(location)s.ControlWord & ~0x87) | 0x06;
+	    	*(__DS402Node_%(location)s.ControlWord) = (*(__DS402Node_%(location)s.ControlWord) & ~0x87) | 0x06;
 	    	break;
 	    case __ReadyToSwitchOn:
-	    	__DS402Node_%(location)s.ControlWord = (__DS402Node_%(location)s.ControlWord & ~0x8f) | 0x07;
-	    	break;
+	    case __OperationEnabled:
+	    	if (!power) {
+	    		*(__DS402Node_%(location)s.ControlWord) = (*(__DS402Node_%(location)s.ControlWord) & ~0x8f) | 0x07;
+	    		break;
+	    	}
 	    case __SwitchedOn:
-	    	// if (POWER) {
-	    	//      __DS402Node_%(location)s.ControlWord = (__DS402Node_%(location)s.ControlWord & ~0x8f) | 0x0f;
-	    	// }
-	    	break;
-	    case __OperationEnabled:
-	    	// if (!POWER) {
-	        //      __DS402Node_%(location)s.ControlWord = (__DS402Node_%(location)s.ControlWord & ~0x8f) | 0x07;
-	    	// }
+	    	if (power) {
+	    	    *(__DS402Node_%(location)s.ControlWord) = (*(__DS402Node_%(location)s.ControlWord) & ~0x8f) | 0x0f;
+	    	}
 	    	break;
 	    case __Fault:
-	    	__DS402Node_%(location)s.ControlWord = (__DS402Node_%(location)s.ControlWord & ~0x8f) | 0x80;
+	    	*(__DS402Node_%(location)s.ControlWord) = (*(__DS402Node_%(location)s.ControlWord) & ~0x8f) | 0x80;
 	    	break;
 	    default:
 	    	break;
 	}
 
-	// DS402 output entries setting
-%(publish_variables)s
+	*(__DS402Node_%(location)s.TargetPosition) = (IEC_DINT)(__DS402Node_%(location)s.axis->PositionSetPoint * __DS402Node_%(location)s.axis->RatioNumerator / __DS402Node_%(location)s.axis->RatioDenominator);
 }