Moved template C code to targets dir. Cleaned up some forgotten print.
authoretisserant
Thu, 21 Aug 2008 17:17:36 +0200
changeset 209 08dc3d064cb5
parent 208 dd630979f628
child 210 ca3bfcf61192
Moved template C code to targets dir. Cleaned up some forgotten print.
plugger.py
runtime/PLCObject.py
runtime/__init__.py
runtime/plc_common_main.c
runtime/plc_debug.c
targets/__init__.py
targets/plc_common_main.c
targets/plc_debug.c
--- a/plugger.py	Thu Aug 21 13:21:37 2008 +0200
+++ b/plugger.py	Thu Aug 21 17:17:36 2008 +0200
@@ -613,7 +613,6 @@
 DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] + \
     ["STEP","TRANSITION","ACTION"]
 
-import runtime
 import re
 import targets
 import connectors
@@ -1039,7 +1038,7 @@
         self.GetIECProgramsAndVariables()
 
         # prepare debug code
-        debug_code = runtime.code("plc_debug") % {
+        debug_code = targets.code("plc_debug") % {
            "programs_declarations":
                "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]),
            "extern_variables_declarations":"\n".join([
@@ -1100,7 +1099,7 @@
            [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls])
 
         # Generate main, based on template
-        plc_main_code = runtime.code("plc_common_main") % {
+        plc_main_code = targets.code("plc_common_main") % {
             "calls_prototypes":"\n".join([(
                   "int __init_%(s)s(int argc,char **argv);\n"+
                   "void __cleanup_%(s)s();\n"+
@@ -1121,7 +1120,7 @@
             }
 
         target_name = self.BeremizRoot.getTargetType().getcontent()["name"]
-        plc_main_code += targets.code(target_name)
+        plc_main_code += targets.targetcode(target_name)
         return plc_main_code
 
         
@@ -1176,7 +1175,6 @@
         os.mkdir(extrafilespath)
         # Then write the files
         for fname,fobject in ExtraFiles:
-            print fname,fobject
             fpath = os.path.join(extrafilespath,fname)
             open(fpath, "wb").write(fobject.read())
         # Now we can forget ExtraFiles (will close files object)
@@ -1439,9 +1437,6 @@
                       for name in os.listdir(extrafilespath) \
                       if not name=="CVS"]
 
-        for filename, unused in extrafiles:
-            print filename
-
         # Send PLC on target
         builder = self.GetBuilder()
         if builder is not None:
--- a/runtime/PLCObject.py	Thu Aug 21 13:21:37 2008 +0200
+++ b/runtime/PLCObject.py	Thu Aug 21 17:17:36 2008 +0200
@@ -24,9 +24,7 @@
 
 import Pyro.core as pyro
 from threading import Timer
-import ctypes, os, dl, commands
-#, sys
-#sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL)
+import ctypes, os, commands
 
 if os.name == ("nt", "ce"):
     from _ctypes import LoadLibrary as dlopen
@@ -42,8 +40,9 @@
      }.get(sys.platform, "")
 
 class PLCObject(pyro.ObjBase):
-    def __init__(self, workingdir, daemon):
+    def __init__(self, workingdir, daemon, argv):
         pyro.ObjBase.__init__(self)
+        self.argv=argv
         self.workingdir = workingdir
         self.PLCStatus = "Stopped"
         self.PLClibraryHandle = None
@@ -142,7 +141,7 @@
                                   "libpan",
                                   "libX11",
                                   ]:
-                    badhandle = dlopen(badlib, dl.RTLD_NOLOAD)
+                    #badhandle = dlopen(badlib, dl.RTLD_NOLOAD)
                     print "Dirty lib detected :" + badlib
                     #dlclose(badhandle)
                     return True
@@ -153,20 +152,24 @@
         print "StartPLC"
         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
             c_argv = ctypes.c_char_p * len(sys.argv)
-            if self._LoadNewPLC() and self._startPLC(len(sys.argv),c_argv(*sys.argv)) == 0:
+            if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0:
                 self.PLCStatus = "Started"
                 return True
             else:
                 print "_StartPLC did not return 0 !"
-        return False
+                self._DoStopPLC()
+        return False
+
+    def _DoStopPLC(self):
+        self._stopPLC()
+        self.PLCStatus = "Stopped"
+        if self._FreePLC():
+            self.PLCStatus = "Dirty"
+        return True
 
     def StopPLC(self):
         if self.PLCStatus == "Started":
-            self._stopPLC()
-            self.PLCStatus = "Stopped"
-            if self._FreePLC():
-                self.PLCStatus = "Dirty"
-            return True
+            self._DoStopPLC()
         return False
 
     def _Reload(self):
--- a/runtime/__init__.py	Thu Aug 21 13:21:37 2008 +0200
+++ b/runtime/__init__.py	Thu Aug 21 17:17:36 2008 +0200
@@ -2,12 +2,5 @@
 
 import os
 
-def code(name):
-    filename = os.path.join(os.path.split(__file__)[0],name + ".c")
-    if os.path.exists(filename):
-        return open(filename).read()
-    else:
-        return "#error %s target not implemented !!!\n"%name
-
 from PLCObject import PLCObject
 import ServicePublisher
--- a/runtime/plc_common_main.c	Thu Aug 21 13:21:37 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Prototypes for function provided by arch-specific code (main)
- * concatained after this template
- ** /
-
-
-/*
- * Functions and variables provied by generated C softPLC
- **/ 
-extern int common_ticktime__;
-
-/*
- * Functions and variables provied by plc.c
- **/ 
-void run(long int tv_sec, long int tv_nsec);
-
-#define maxval(a,b) ((a>b)?a:b)
-
-#include "iec_types.h"
-/*#include "stdio.h" /* For debug */
-
-/*
- * Functions and variables provied by generated C softPLC
- **/ 
-void config_run__(int tick);
-void config_init__(void);
-
-/*
- *  Functions and variables to export to generated C softPLC and plugins
- **/
- 
-IEC_TIME __CURRENT_TIME;
-int __tick = 0;
-
-static int init_level = 0;
-static int Debugging = 1;
-
-/*
- * Prototypes of functions exported by plugins 
- **/
-%(calls_prototypes)s
-
-/*
- * Retrieve input variables, run PLC and publish output variables 
- **/
-void __run()
-{
-    %(retrieve_calls)s
-
-    if(Debugging) __retrieve_debug();
-    
-    config_run__(__tick);
-
-    if(Debugging) __publish_debug();
-    
-    %(publish_calls)s
-
-    __tick++;
-}
-
-/*
- * Initialize variables according to PLC's defalut values,
- * and then init plugins with that values  
- **/
-int __init(int argc,char **argv)
-{
-    int res;
-    config_init__();
-    %(init_calls)s
-    return 0;
-}
-/*
- * Calls plugin cleanup proc.
- **/
-void __cleanup()
-{
-    %(cleanup_calls)s
-}
-
-
-void PLC_GetTime(IEC_TIME *CURRENT_TIME);
-void PLC_SetTimer(long long next, long long period);
-
-#define CALIBRATED -2
-#define NOT_CALIBRATED -1
-static int calibration_count = NOT_CALIBRATED;
-static IEC_TIME cal_begin;
-static long long Tsync = 0;
-static long long FreqCorr = 0;
-static int Nticks = 0;
-static int  last_tick = 0;
-static long long Ttick = 0;
-#define mod %%
-/*
- * Call this on each external sync, 
- * @param sync_align_ratio 0->100 : align ratio, < 0 : no align, calibrate period 
- **/
-void align_tick(int sync_align_ratio)
-{
-	/*
-	printf("align_tick(%%d)\n", calibrate);
-	*/
-	if(sync_align_ratio < 0){ /* Calibration */
-		if(calibration_count == CALIBRATED)
-			/* Re-calibration*/
-			calibration_count = NOT_CALIBRATED;
-		if(calibration_count == NOT_CALIBRATED)
-			/* Calibration start, get time*/
-			PLC_GetTime(&cal_begin);
-		calibration_count++;
-	}else{ /* do alignment (if possible) */
-		if(calibration_count >= 0){
-			/* End of calibration */
-			/* Get final time */
-			IEC_TIME cal_end;
-			PLC_GetTime(&cal_end);
-			/*adjust calibration_count*/
-			calibration_count++;
-			/* compute mean of Tsync, over calibration period */	
-			Tsync = ((long long)(cal_end.tv_sec - cal_begin.tv_sec) * (long long)1000000000 +
-					(cal_end.tv_nsec - cal_begin.tv_nsec)) / calibration_count;
-			if( (Nticks = (Tsync / Ttick)) > 0){
-				FreqCorr = (Tsync mod Ttick); /* to be divided by Nticks */
-			}else{
-				FreqCorr = Tsync - (Ttick mod Tsync);
-			}
-			/*
-			printf("Tsync = %%ld\n", Tsync);
-			printf("calibration_count = %%d\n", calibration_count);
-			printf("Nticks = %%d\n", Nticks);
-			*/
-			calibration_count = CALIBRATED;
-		}
-		if(calibration_count == CALIBRATED){
-			/* Get Elapsed time since last PLC tick (__CURRENT_TIME) */
-			IEC_TIME now;
-			long long elapsed;
-			long long Tcorr;
-			long long PhaseCorr;
-			long long PeriodicTcorr;
-			PLC_GetTime(&now);
-			elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec;
-			if(Nticks > 0){
-				PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */
-				Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks;
-				if(Nticks < 2){
-					/* When Sync source period is near Tick time */
-					/* PhaseCorr may not be applied to Periodic time given to timer */
-					PeriodicTcorr = Ttick + FreqCorr / Nticks;
-				}else{
-					PeriodicTcorr = Tcorr; 
-				}
-			}else if(__tick > last_tick){
-				last_tick = __tick;
-				PhaseCorr = elapsed - (Tsync*sync_align_ratio/100);
-				PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr;
-			}else{
-				/*PLC did not run meanwhile. Nothing to do*/
-				return;
-			}
-			/* DO ALIGNEMENT */
-			PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr);
-		}
-	}
-}
-
-int suspendDebug()
-{
-    /* Prevent PLC to enter debug code */
-    Debugging = 0;
-}
-
-int resumeDebug()
-{
-    /* Let PLC enter debug code */
-    Debugging = 1;
-}
--- a/runtime/plc_debug.c	Thu Aug 21 13:21:37 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * DEBUGGER code
- * 
- * On "publish", when buffer is free, debugger stores arbitrary variables 
- * content into, and mark this buffer as filled
- * 
- * 
- * Buffer content is read asynchronously, (from non real time part), 
- * and then buffer marked free again.
- *  
- * 
- * */
-#include "iec_types_all.h"
-#include "POUS.h"
-/*for memcpy*/
-#include <string.h>
-
-#define BUFFER_SIZE 1024
-#define MAX_SUBSCRIBTION %(subscription_table_count)d
-
-/* Atomically accessed variable for buffer state */
-#define BUFFER_FREE 0
-#define BUFFER_BUSY 1
-static long buffer_state = BUFFER_FREE;
-
-/* The buffer itself */
-char debug_buffer[BUFFER_SIZE];
-
-/* Buffer's cursor*/
-static char* buffer_cursor = debug_buffer;
-
-typedef struct{
-    void* ptrvalue;
-    __IEC_types_enum type;
-}struct_plcvar;
-
-/***
- * Declare programs 
- **/
-%(programs_declarations)s
-
-/***
- * Declare global variables from resources and conf 
- **/
-%(extern_variables_declarations)s
-
-static int subscription_table[MAX_SUBSCRIBTION];
-static int* latest_subscription = subscription_table;
-static int* subscription_cursor = subscription_table;
-
-struct_plcvar variable_table[%(variables_pointer_type_table_count)d];
-
-void __init_debug()
-{
-%(variables_pointer_type_table_initializer)s
-};
-
-void __cleanup_debug()
-{
-}
-
-void __retrieve_debug()
-{
-}
-
-void __publish_debug()
-{
-    /* Lock buffer */
-    long latest_state = AtomicCompareExchange(
-        &buffer_state,
-        BUFFER_FREE,
-        BUFFER_BUSY);
-        
-    /* If buffer was free */
-    if(latest_state == BUFFER_FREE)
-    {
-        int* subscription;
-        
-        /* Reset buffer cursor */
-        buffer_cursor = debug_buffer;
-        
-        /* iterate over subscriptions */
-        for(subscription=subscription_table;
-            subscription < latest_subscription;
-            subscription++)
-        {
-            /* get variable descriptor */
-            struct_plcvar* my_var = &variable_table[*subscription];
-            char* next_cursor;
-            /* get variable size*/
-            USINT size = __get_type_enum_size(my_var->type);
-            /* compute next cursor positon*/
-            next_cursor = buffer_cursor + size;
-            /* if buffer not full */
-            if(next_cursor < debug_buffer + BUFFER_SIZE)
-            {
-                /* copy data to the buffer */
-                memcpy(buffer_cursor, my_var->ptrvalue, size);
-                /* increment cursor according size*/
-                buffer_cursor = next_cursor;
-            }else{
-                /*TODO : signal overflow*/
-            }
-        }
-
-        /* Reset buffer cursor again (for IterDebugData)*/
-        buffer_cursor = debug_buffer;
-        subscription_cursor = subscription_table;
-        
-        /* Trigger asynchronous transmission (returns immediately) */
-        InitiateDebugTransfer(); /* size */
-    }
-}
-
-void RegisterDebugVariable(int idx)
-{
-    /*If subscription table not full */
-    if(latest_subscription - subscription_table < MAX_SUBSCRIBTION)
-    {
-        *(latest_subscription++) = idx;
-        /* TODO pre-calc buffer size and signal overflow*/
-    }else{
-        /*TODO : signal subscription overflow*/
-    }
-}
-
-void ResetDebugVariables(void)
-{
-    latest_subscription = subscription_table;
-}
-
-void FreeDebugData()
-{
-    /* atomically mark buffer as free */
-    long latest_state = AtomicCompareExchange(
-        &buffer_state,
-        BUFFER_BUSY,
-        BUFFER_FREE);
-}
-
-void* IterDebugData(int* idx, const char **type_name)
-{
-    if(subscription_cursor < latest_subscription){
-        *idx = *subscription_cursor;
-        struct_plcvar* my_var = &variable_table[*subscription_cursor++];
-        *type_name = __get_type_enum_name(my_var->type);
-        return my_var->ptrvalue;
-    }
-    return NULL;
-}
-
--- a/targets/__init__.py	Thu Aug 21 13:21:37 2008 +0200
+++ b/targets/__init__.py	Thu Aug 21 17:17:36 2008 +0200
@@ -64,11 +64,14 @@
 for target in DictXSD_target.keys():
     targetchoices += DictXSD_target[target]
 
-def code(target_name):
-    filename = path.join(path.split(__file__)[0], target_name, "plc_%s_main.c"%target_name)
-    if path.exists(filename):
-        return open(filename).read()
-    else:
-        return "#error %s target not implemented !!!\n"%target_name
+def targetcode(target_name, code_name=None):
+    if code_name is None:
+        code_name="plc_%s_main.c"%target_name
+    filename = path.join(path.split(__file__)[0], target_name, code_name)
+    return open(filename).read()
+
+def code(name):
+    filename = path.join(path.split(__file__)[0],name + ".c")
+    return open(filename).read()
 
 from toolchain_gcc import toolchain_gcc
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/plc_common_main.c	Thu Aug 21 17:17:36 2008 +0200
@@ -0,0 +1,177 @@
+/*
+ * Prototypes for function provided by arch-specific code (main)
+ * concatained after this template
+ ** /
+
+
+/*
+ * Functions and variables provied by generated C softPLC
+ **/ 
+extern int common_ticktime__;
+
+/*
+ * Functions and variables provied by plc.c
+ **/ 
+void run(long int tv_sec, long int tv_nsec);
+
+#define maxval(a,b) ((a>b)?a:b)
+
+#include "iec_types.h"
+/*#include "stdio.h" /* For debug */
+
+/*
+ * Functions and variables provied by generated C softPLC
+ **/ 
+void config_run__(int tick);
+void config_init__(void);
+
+/*
+ *  Functions and variables to export to generated C softPLC and plugins
+ **/
+ 
+IEC_TIME __CURRENT_TIME;
+int __tick = 0;
+
+static int init_level = 0;
+static int Debugging = 1;
+
+/*
+ * Prototypes of functions exported by plugins 
+ **/
+%(calls_prototypes)s
+
+/*
+ * Retrieve input variables, run PLC and publish output variables 
+ **/
+void __run()
+{
+    %(retrieve_calls)s
+
+    if(Debugging) __retrieve_debug();
+    
+    config_run__(__tick);
+
+    if(Debugging) __publish_debug();
+    
+    %(publish_calls)s
+
+    __tick++;
+}
+
+/*
+ * Initialize variables according to PLC's defalut values,
+ * and then init plugins with that values  
+ **/
+int __init(int argc,char **argv)
+{
+    int res;
+    config_init__();
+    %(init_calls)s
+    return 0;
+}
+/*
+ * Calls plugin cleanup proc.
+ **/
+void __cleanup()
+{
+    %(cleanup_calls)s
+}
+
+
+void PLC_GetTime(IEC_TIME *CURRENT_TIME);
+void PLC_SetTimer(long long next, long long period);
+
+#define CALIBRATED -2
+#define NOT_CALIBRATED -1
+static int calibration_count = NOT_CALIBRATED;
+static IEC_TIME cal_begin;
+static long long Tsync = 0;
+static long long FreqCorr = 0;
+static int Nticks = 0;
+static int  last_tick = 0;
+static long long Ttick = 0;
+#define mod %%
+/*
+ * Call this on each external sync, 
+ * @param sync_align_ratio 0->100 : align ratio, < 0 : no align, calibrate period 
+ **/
+void align_tick(int sync_align_ratio)
+{
+	/*
+	printf("align_tick(%%d)\n", calibrate);
+	*/
+	if(sync_align_ratio < 0){ /* Calibration */
+		if(calibration_count == CALIBRATED)
+			/* Re-calibration*/
+			calibration_count = NOT_CALIBRATED;
+		if(calibration_count == NOT_CALIBRATED)
+			/* Calibration start, get time*/
+			PLC_GetTime(&cal_begin);
+		calibration_count++;
+	}else{ /* do alignment (if possible) */
+		if(calibration_count >= 0){
+			/* End of calibration */
+			/* Get final time */
+			IEC_TIME cal_end;
+			PLC_GetTime(&cal_end);
+			/*adjust calibration_count*/
+			calibration_count++;
+			/* compute mean of Tsync, over calibration period */	
+			Tsync = ((long long)(cal_end.tv_sec - cal_begin.tv_sec) * (long long)1000000000 +
+					(cal_end.tv_nsec - cal_begin.tv_nsec)) / calibration_count;
+			if( (Nticks = (Tsync / Ttick)) > 0){
+				FreqCorr = (Tsync mod Ttick); /* to be divided by Nticks */
+			}else{
+				FreqCorr = Tsync - (Ttick mod Tsync);
+			}
+			/*
+			printf("Tsync = %%ld\n", Tsync);
+			printf("calibration_count = %%d\n", calibration_count);
+			printf("Nticks = %%d\n", Nticks);
+			*/
+			calibration_count = CALIBRATED;
+		}
+		if(calibration_count == CALIBRATED){
+			/* Get Elapsed time since last PLC tick (__CURRENT_TIME) */
+			IEC_TIME now;
+			long long elapsed;
+			long long Tcorr;
+			long long PhaseCorr;
+			long long PeriodicTcorr;
+			PLC_GetTime(&now);
+			elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec;
+			if(Nticks > 0){
+				PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */
+				Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks;
+				if(Nticks < 2){
+					/* When Sync source period is near Tick time */
+					/* PhaseCorr may not be applied to Periodic time given to timer */
+					PeriodicTcorr = Ttick + FreqCorr / Nticks;
+				}else{
+					PeriodicTcorr = Tcorr; 
+				}
+			}else if(__tick > last_tick){
+				last_tick = __tick;
+				PhaseCorr = elapsed - (Tsync*sync_align_ratio/100);
+				PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr;
+			}else{
+				/*PLC did not run meanwhile. Nothing to do*/
+				return;
+			}
+			/* DO ALIGNEMENT */
+			PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr);
+		}
+	}
+}
+
+int suspendDebug()
+{
+    /* Prevent PLC to enter debug code */
+    Debugging = 0;
+}
+
+int resumeDebug()
+{
+    /* Let PLC enter debug code */
+    Debugging = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/plc_debug.c	Thu Aug 21 17:17:36 2008 +0200
@@ -0,0 +1,151 @@
+/*
+ * DEBUGGER code
+ * 
+ * On "publish", when buffer is free, debugger stores arbitrary variables 
+ * content into, and mark this buffer as filled
+ * 
+ * 
+ * Buffer content is read asynchronously, (from non real time part), 
+ * and then buffer marked free again.
+ *  
+ * 
+ * */
+#include "iec_types_all.h"
+#include "POUS.h"
+/*for memcpy*/
+#include <string.h>
+
+#define BUFFER_SIZE 1024
+#define MAX_SUBSCRIBTION %(subscription_table_count)d
+
+/* Atomically accessed variable for buffer state */
+#define BUFFER_FREE 0
+#define BUFFER_BUSY 1
+static long buffer_state = BUFFER_FREE;
+
+/* The buffer itself */
+char debug_buffer[BUFFER_SIZE];
+
+/* Buffer's cursor*/
+static char* buffer_cursor = debug_buffer;
+
+typedef struct{
+    void* ptrvalue;
+    __IEC_types_enum type;
+}struct_plcvar;
+
+/***
+ * Declare programs 
+ **/
+%(programs_declarations)s
+
+/***
+ * Declare global variables from resources and conf 
+ **/
+%(extern_variables_declarations)s
+
+static int subscription_table[MAX_SUBSCRIBTION];
+static int* latest_subscription = subscription_table;
+static int* subscription_cursor = subscription_table;
+
+struct_plcvar variable_table[%(variables_pointer_type_table_count)d];
+
+void __init_debug()
+{
+%(variables_pointer_type_table_initializer)s
+};
+
+void __cleanup_debug()
+{
+}
+
+void __retrieve_debug()
+{
+}
+
+void __publish_debug()
+{
+    /* Lock buffer */
+    long latest_state = AtomicCompareExchange(
+        &buffer_state,
+        BUFFER_FREE,
+        BUFFER_BUSY);
+        
+    /* If buffer was free */
+    if(latest_state == BUFFER_FREE)
+    {
+        int* subscription;
+        
+        /* Reset buffer cursor */
+        buffer_cursor = debug_buffer;
+        
+        /* iterate over subscriptions */
+        for(subscription=subscription_table;
+            subscription < latest_subscription;
+            subscription++)
+        {
+            /* get variable descriptor */
+            struct_plcvar* my_var = &variable_table[*subscription];
+            char* next_cursor;
+            /* get variable size*/
+            USINT size = __get_type_enum_size(my_var->type);
+            /* compute next cursor positon*/
+            next_cursor = buffer_cursor + size;
+            /* if buffer not full */
+            if(next_cursor < debug_buffer + BUFFER_SIZE)
+            {
+                /* copy data to the buffer */
+                memcpy(buffer_cursor, my_var->ptrvalue, size);
+                /* increment cursor according size*/
+                buffer_cursor = next_cursor;
+            }else{
+                /*TODO : signal overflow*/
+            }
+        }
+
+        /* Reset buffer cursor again (for IterDebugData)*/
+        buffer_cursor = debug_buffer;
+        subscription_cursor = subscription_table;
+        
+        /* Trigger asynchronous transmission (returns immediately) */
+        InitiateDebugTransfer(); /* size */
+    }
+}
+
+void RegisterDebugVariable(int idx)
+{
+    /*If subscription table not full */
+    if(latest_subscription - subscription_table < MAX_SUBSCRIBTION)
+    {
+        *(latest_subscription++) = idx;
+        /* TODO pre-calc buffer size and signal overflow*/
+    }else{
+        /*TODO : signal subscription overflow*/
+    }
+}
+
+void ResetDebugVariables(void)
+{
+    latest_subscription = subscription_table;
+}
+
+void FreeDebugData()
+{
+    /* atomically mark buffer as free */
+    long latest_state = AtomicCompareExchange(
+        &buffer_state,
+        BUFFER_BUSY,
+        BUFFER_FREE);
+}
+
+void* IterDebugData(int* idx, const char **type_name)
+{
+    if(subscription_cursor < latest_subscription){
+        *idx = *subscription_cursor;
+        struct_plcvar* my_var = &variable_table[*subscription_cursor++];
+        *type_name = __get_type_enum_name(my_var->type);
+        return my_var->ptrvalue;
+    }
+    return NULL;
+}
+