Browse Source

Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov

Suren A. Chilingaryan 8 years ago
parent
commit
f7636162ba
86 changed files with 1191 additions and 1113 deletions
  1. 7 3
      CMakeLists.txt
  2. 8 6
      apps/test_multithread.c
  3. 11 2
      pcilib/error.c
  4. 55 14
      pcilib/py.c
  5. 144 126
      pyserver/api_server.py
  6. 231 0
      pyserver/html_server.py
  7. 10 0
      pyserver/scripts/test_script.py
  8. 4 0
      pyserver/scripts/test_script2.py
  9. 46 0
      pyserver/static/base.css
  10. 4 0
      pyserver/static/check_err.js
  11. 0 0
      pyserver/static/codebase/dhtmlx.css
  12. 0 0
      pyserver/static/codebase/dhtmlx.js
  13. 0 0
      pyserver/static/codebase/dhtmlx_deprecated.js
  14. 0 0
      pyserver/static/codebase/ext/dhxupload.xap
  15. 0 0
      pyserver/static/codebase/ext/swfobject.js
  16. 0 0
      pyserver/static/codebase/ext/uploader.swf
  17. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/blank.gif
  18. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/but_cut.gif
  19. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/folderClosed.gif
  20. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/folderOpen.gif
  21. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckAll.gif
  22. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckDis.gif
  23. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckGray.gif
  24. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/iconUncheckAll.gif
  25. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/iconUncheckDis.gif
  26. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/leaf.gif
  27. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line.gif
  28. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line1.gif
  29. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line1_rtl.gif
  30. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line2.gif
  31. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line2_rtl.gif
  32. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line3.gif
  33. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line3_rtl.gif
  34. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line4.gif
  35. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/line4_rtl.gif
  36. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/lock.gif
  37. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus.gif
  38. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus1.gif
  39. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus2.gif
  40. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus2_rtl.gif
  41. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus3.gif
  42. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus3_rtl.gif
  43. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus4.gif
  44. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus4_rtl.gif
  45. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus5.gif
  46. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/minus5_rtl.gif
  47. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus.gif
  48. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus1.gif
  49. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus2.gif
  50. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus2_rtl.gif
  51. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus3.gif
  52. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus3_rtl.gif
  53. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus4.gif
  54. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus4_rtl.gif
  55. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus5.gif
  56. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/plus5_rtl.gif
  57. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/radio_off.gif
  58. 0 0
      pyserver/static/codebase/imgs/dhxtree_skyblue/radio_on.gif
  59. 0 0
      pyserver/static/codebase/thirdparty/excanvas/AUTHORS
  60. 0 0
      pyserver/static/codebase/thirdparty/excanvas/COPYING
  61. 0 0
      pyserver/static/codebase/thirdparty/excanvas/README
  62. 0 0
      pyserver/static/codebase/thirdparty/excanvas/excanvas.js
  63. 0 0
      pyserver/static/jquery-2.2.1.js
  64. 194 0
      pyserver/templates/base.html
  65. 91 0
      pyserver/templates/property_info.html
  66. 9 0
      pyserver/templates/register_info.html
  67. 100 0
      pyserver/templates/registers/table_cell.html
  68. 10 0
      pyserver/templates/registers/table_header.html
  69. 42 0
      pyserver/templates/registers/table_scripts.html
  70. 12 0
      pyserver/templates/registers_list.html
  71. 2 7
      pywrap/CMakeLists.txt
  72. 0 197
      pywrap/html_server.py
  73. 38 0
      pywrap/pcilib.py
  74. 91 85
      pywrap/pcipywrap.c
  75. 19 19
      pywrap/pcipywrap.h
  76. 5 5
      pywrap/pcipywrap.i
  77. 0 347
      pywrap/templates/base.html
  78. 0 91
      pywrap/templates/property_info.html
  79. 0 106
      pywrap/templates/register_info.html
  80. 0 26
      pywrap/templates/registers_list.html
  81. 31 26
      pywrap/test_pcilib.py
  82. 1 1
      run
  83. 0 50
      xml/test/cmosis.xml
  84. 1 0
      xml/test/props.xml
  85. 1 2
      xml/test/test_prop2.py
  86. 24 0
      xml/test/test_prop4.py

+ 7 - 3
CMakeLists.txt

@@ -1,6 +1,6 @@
 project(pcitool)
 
-set(PCILIB_VERSION "0.2.6")
+set(PCILIB_VERSION "0.2.7")
 set(PCILIB_ABI_VERSION "2")
 
 cmake_minimum_required(VERSION 2.8)
@@ -38,8 +38,11 @@ find_package(PkgConfig REQUIRED)
 find_package(Threads REQUIRED)
 
 if (NOT DISABLE_PYTHON)
-    find_package(PythonLibs 2.7 REQUIRED)
-    find_package(PythonInterp 2.7 REQUIRED)
+    set(PYTHON_VERSION 2.7 CACHE STRING "python version")
+
+    find_package(PythonInterp ${PYTHON_VERSION} REQUIRED)
+    find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED)
+
     find_package(SWIG REQUIRED)
     if (NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING)
 	message (FATAL_ERROR "Version mismatch between python interpreter and libraries")
@@ -128,6 +131,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINA
 
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
     file(COPY ${CMAKE_SOURCE_DIR}/xml DESTINATION ${CMAKE_BINARY_DIR})
+    file(COPY ${CMAKE_SOURCE_DIR}/pyserver DESTINATION ${CMAKE_BINARY_DIR})
     file(COPY ${CMAKE_SOURCE_DIR}/pci
 	 DESTINATION ${CMAKE_BINARY_DIR}
 	 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE

+ 8 - 6
apps/test_multithread.c

@@ -1,8 +1,10 @@
 #include <stdio.h>
 #include <pthread.h>
-#include "pcilib.h"
 #include <stdlib.h>
 
+#include "pcilib.h"
+#include "pcilib/error.h"
+
 const char* prop = "/registers/fpga/reg1";
 char* reg;
 int stop = 0;
@@ -18,14 +20,14 @@ void *get_prop(void *arg)
         err = pcilib_get_property(ctx, prop, &val);
         if(err)
         {
-            printf("err pcilib_read_register\n");
+            pcilib_error("Error in pcilib_read_register");
             return NULL;
         }
         long value = pcilib_get_value_as_int(ctx, &val, &err);
         pcilib_clean_value(ctx, &val);
         if(err)
         {
-            printf("err pcilib_get_value_as_int\n");
+            pcilib_error("Error in pcilib_get_value_as_int");
             return NULL;
         }
         printf("reg = %li\n", value);
@@ -47,20 +49,20 @@ void *read_reg(void *arg)
 
         if(err)
         {
-            printf("err pcilib_read_register\n");
+            pcilib_error("Error in pcilib_read_register");
             return NULL;
         }
         err = pcilib_set_value_from_register_value(ctx, &val, reg_val);
         if(err)
         {
-            printf("err pcilib_set_value_from_register_value\n");
+            pcilib_error("Error in pcilib_set_value_from_register_value");
             return NULL;
         }
         long value = pcilib_get_value_as_int(ctx, &val, &err);
         pcilib_clean_value(ctx, &val);
         if(err)
         {
-            printf("err pcilib_get_value_as_int\n");
+            pcilib_error("Error in pcilib_get_value_as_int");
             return NULL;
         }
         printf("reg = %li\n", value);

+ 11 - 2
pcilib/error.c

@@ -12,8 +12,17 @@
 #define PCILIB_LOGGER_HISTORY 16
 
 void pcilib_print_error(void *arg, const char *file, int line, pcilib_log_priority_t prio, const char *msg, va_list va) {
-    vprintf(msg, va);
-    printf(" [%s:%d]\n", file, line);
+    size_t size = strlen(msg) + strlen(file) + 64;
+    char *stmp = alloca(size * sizeof(char*));
+
+    if (stmp) {
+	sprintf(stmp, "%s [%s:%d]\n", msg, file, line);
+	vprintf(stmp, va);
+    } else {
+	    // Bad for multithreading...
+	vprintf(msg, va);
+	printf(" [%s:%d]\n", file, line);
+    }
 }
 
 static void *pcilib_logger_argument = NULL;

+ 55 - 14
pcilib/py.c

@@ -17,6 +17,8 @@
 #include "error.h"
 
 #ifdef HAVE_PYTHON
+#define PCILIB_PYTHON_WRAPPER "pcipywrap"
+
 typedef struct pcilib_script_s pcilib_script_t;
 
 struct pcilib_script_s {
@@ -43,18 +45,41 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag
     PyGILState_STATE gstate;
     PyObject *pytype = NULL;
     PyObject *pyval = NULL;
+    PyObject *pystr = NULL;
     PyObject *pytraceback = NULL;
 
 
     gstate = PyGILState_Ensure();
     if (PyErr_Occurred()) {
 	PyErr_Fetch(&pytype, &pyval, &pytraceback);
-	type = PyString_AsString(pytype);
-	val = PyString_AsString(pyval);
+	PyErr_NormalizeException(&pytype, &pyval, &pytraceback);
+	if (pyval) pystr = PyObject_Str(pyval);
+
+# if PY_MAJOR_VERSION >= 3
+	if (pytype) {
+	    if (PyUnicode_Check(pytype))
+		type = PyUnicode_AsUTF8(pytype);
+	    else
+		type = PyExceptionClass_Name(pytype);
+	}
+	if (pystr) {
+	    val = PyUnicode_AsUTF8(pystr);
+	}
+# else /* PY_MAJOR_VERSION >= 3 */
+	if (pytype) {
+	    if (PyString_Check(pytype))
+		type = PyString_AsString(pytype);
+	    else
+		type = PyExceptionClass_Name(pytype);
+	}
+	if (pystr) {
+	    val = PyString_AsString(pystr);
+	}
+# endif /*PY_MAJOR_VERSION >= 3*/
     }
     PyGILState_Release(gstate);
 #endif /* HAVE_PYTHON */
-    
+
     va_start(va, msg);
     if (type) {
 	char *str;
@@ -83,6 +108,7 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag
     va_end(va);
 
 #ifdef HAVE_PYTHON
+    if (pystr) Py_DECREF(pystr);
     if (pytype) Py_DECREF(pytype);
     if (pyval) Py_DECREF(pyval);
     if (pytraceback) Py_DECREF(pytraceback);
@@ -119,14 +145,14 @@ int pcilib_init_py(pcilib_t *ctx) {
         return PCILIB_ERROR_FAILED;
     }
 
-    PyObject *pywrap = PyImport_ImportModule("pcipywrap");
+    PyObject *pywrap = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER);
     if (!pywrap) {
 	pcilib_python_error("Error importing pcilib python wrapper");
 	return PCILIB_ERROR_FAILED;
     }
 	
-    PyObject *mod_name = PyString_FromString("Pcipywrap");
-    PyObject *pyctx = PyCObject_FromVoidPtr(ctx, NULL);
+    PyObject *mod_name = PyUnicode_FromString(PCILIB_PYTHON_WRAPPER);
+    PyObject *pyctx = PyCapsule_New(ctx, "pcilib", NULL);
     ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(pywrap, mod_name, pyctx, NULL);
     Py_XDECREF(pyctx);
     Py_XDECREF(mod_name);
@@ -166,7 +192,7 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
 	return PCILIB_ERROR_FAILED;
     }
 
-    pynewdir = PyString_FromString(script_dir);
+    pynewdir = PyUnicode_FromString(script_dir);
     if (!pynewdir) {
 	pcilib_python_error("Can't create python string");
 	return PCILIB_ERROR_MEMORY;
@@ -175,13 +201,13 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
 	// Checking if the directory already in the path?
     pydict = PyDict_New();
     if (pydict) {
-	pystr = PyString_FromString("cur");
+	pystr = PyUnicode_FromString("cur");
         if (pystr) {
 	    PyDict_SetItem(pydict, pystr, pynewdir);
 	    Py_DECREF(pystr);
 	}
 
-	pystr = PyString_FromString("path");
+	pystr = PyUnicode_FromString("path");
 	if (pystr) {
 	    PyDict_SetItem(pydict, pystr, pypath);
 	    Py_DECREF(pystr);
@@ -292,13 +318,13 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_
 	return PCILIB_ERROR_FAILED;
     }
     
-    pystr = PyString_FromString("read_from_register");
+    pystr = PyUnicode_FromString("read_from_register");
     if (pystr) {
 	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
 	Py_DECREF(pystr);
     }
 
-    pystr = PyString_FromString("write_to_register");
+    pystr = PyUnicode_FromString("write_to_register");
     if (pystr) {
 	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
 	Py_DECREF(pystr);
@@ -322,7 +348,7 @@ pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *va
     switch(val->type) {
      case PCILIB_TYPE_LONG:
 	ival = pcilib_get_value_as_int(ctx, val, &err);
-	if (!err) res = (PyObject*)PyInt_FromLong(ival);
+	if (!err) res = (PyObject*)PyLong_FromLong(ival);
 	break;
      case PCILIB_TYPE_DOUBLE:
 	fval = pcilib_get_value_as_float(ctx, val, &err);
@@ -359,12 +385,27 @@ int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py
     PyGILState_STATE gstate;
 	
     gstate = PyGILState_Ensure();
-    if (PyInt_Check(pyval)) {
-        err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
+    if (PyLong_Check(pyval)) {
+        err = pcilib_set_value_from_int(ctx, val, PyLong_AsLong(pyval));
     } else if (PyFloat_Check(pyval)) {
         err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyval));
+#if PY_MAJOR_VERSION < 3
+    } else if (PyInt_Check(pyval)) {
+        err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
     } else if (PyString_Check(pyval)) {
         err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
+    } else if (PyUnicode_Check(pyval)) {
+        PyObject *buf = PyUnicode_AsASCIIString(pyval);
+        if (buf) {
+    	    err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf));
+    	    Py_DecRef(buf);
+    	} else {
+    	    err = PCILIB_ERROR_FAILED;
+	}
+#else /* PY_MAJOR_VERSION < 3 */
+    } else if (PyUnicode_Check(pyval)) {
+        err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval));
+#endif /* PY_MAJOR_VERSION < 3 */
     } else {
         PyGILState_Release(gstate);
         pcilib_error("Can't convert PyObject to polymorphic pcilib value");

+ 144 - 126
pywrap/server.py → pyserver/api_server.py

@@ -1,26 +1,28 @@
-import time
 import os
-import pcipywrap
-import json
 import sys
-from optparse import OptionParser
 
-from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
-from SocketServer import ThreadingMixIn
-import threading
+import pcilib
 
-pcilib = None
+import time
+import json
+from optparse import OptionParser
+from multiprocessing import Process
+
+if sys.version_info >= (3,0):
+   from http.server import HTTPServer, BaseHTTPRequestHandler
+   from socketserver import ThreadingMixIn
+else:
+   from SocketServer import ThreadingMixIn
+   from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
 
 class MultiThreadedHTTPServer(ThreadingMixIn, HTTPServer):
     pass
 
 class PcilibServerHandler(BaseHTTPRequestHandler):
-   locks = list()
-   lock_global = 0
    
-   #def __init__(s, pcilib, *args):
-   #   s.pcilib = pcilib
-   #   BaseHTTPRequestHandler.__init__(s, *args)
+   def __init__(s, pcilib, *args):
+      s.pcilib = pcilib
+      BaseHTTPRequestHandler.__init__(s, *args)
    
    def do_HEAD(s):
       s.send_response(200)
@@ -28,6 +30,12 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
       s.end_headers()
       
    def do_GET(s):
+      #run request in separate process
+      p = Process(target=s.do_GET_worker, args=())
+      p.start()
+      p.join()
+      
+   def do_GET_worker(s):
       length = int(s.headers['Content-Length'])
       
       #deserialize input data
@@ -73,7 +81,7 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
 
             registers = dict()
             try:
-               registers = pcilib.get_registers_list(bank)
+               registers = s.pcilib.get_registers_list(bank)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -101,7 +109,7 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             
             register = dict()
             try:
-               register = pcilib.get_register_info(reg, bank)
+               register = s.pcilib.get_register_info(reg, bank)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -119,7 +127,7 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             
             properties = dict()
             try:
-               properties = pcilib.get_property_list(branch)
+               properties = s.pcilib.get_property_list(branch)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -142,12 +150,12 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             #parse command arguments and convert them to string
             reg = str(data.get('reg', None))
             bank = data.get('bank', None)
-            if not bank is None:
-				   bank = str(bank)
+            if(not bank is None):
+               bank = str(bank)
             
             value = 0
             try:
-               value = pcilib.read_register(reg, bank)
+               value = s.pcilib.read_register(reg, bank)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -174,13 +182,13 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
                
             #parse command arguments and convert them to string
             reg = str(data.get('reg', None))
-            value = str(data.get('value', None))
+            value = data.get('value', None)
             bank = data.get('bank', None)
-            if not bank is None:
-				   bank = str(bank)
+            if(not bank is None):
+               bank = str(bank)
             
             try:
-               pcilib.write_register(value, reg, bank)
+               s.pcilib.write_register(value, reg, bank)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -202,7 +210,7 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             
             value = 0
             try:
-               value = pcilib.get_property(prop)
+               value = s.pcilib.get_property(prop)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -226,13 +234,13 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
                s.error('message doesnt contains "value" field, '
                        'which is required for "set_property" command', data)
                return
-               
+            
             #parse command arguments and convert them to string
             prop = str(data.get('prop', None))
-            value = str(data.get('value', None))
+            value = data.get('value', None)
             
             try:
-               pcilib.set_property(value, prop)
+               s.pcilib.set_property(value, prop)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -252,20 +260,11 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             #parse command arguments and convert them to string
             lock_id = str(data.get('lock_id'))
             
-            #check if lock already setted
-            #if lock_id in PcilibServerHandler.locks:
-            #   s.error('Lock with id: ' + lock_id + 
-            #           'already setted by this server',
-            #           data)
-            #   return
-            
             try:
-               pcilib.lock(lock_id)
+               s.pcilib.lock(lock_id)
             except Exception as e:
                s.error(str(e), data) 
                return
-               
-            PcilibServerHandler.locks.append(lock_id)
             
             #Success! Create and send reply
             s.wrapMessageAndSend({'status': 'ok'}, data)
@@ -283,7 +282,7 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             lock_id = str(data.get('lock_id'))
             
             try:
-               pcilib.try_lock(lock_id)
+               s.pcilib.try_lock(lock_id)
             except Exception as e:
                s.error(str(e), data) 
                return
@@ -295,45 +294,75 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
             
          elif(command == 'unlock'):
             #check required arguments
-            #if not 'lock_id' in data:
-            #   s.error('message doesnt contains "lock_id" field, '
-            #           'which is required for "unlock" command', data)
-            #   return
+            if not 'lock_id' in data:
+               s.error('message doesnt contains "lock_id" field, '
+                       'which is required for "unlock" command', data)
+               return
                
             #parse command arguments and convert them to string
-            #lock_id = str(data.get('lock_id'))
-            
-            #try:
-            #   pcilib.unlock(lock_id)
-            #except Exception as e:
-            #   s.error(str(e), data) 
-            #   return
-            #
-            #remove lock from locks list
-            #if lock_id in PcilibServerHandler.locks:
-            #   PcilibServerHandler.locks.remove(lock_id)
-            time.sleep(20)
+            lock_id = str(data.get('lock_id'))
+            
+            try:
+               s.pcilib.unlock(lock_id)
+            except Exception as e:
+               s.error(str(e), data) 
+               return
+
             #Success! Create and send reply
             s.wrapMessageAndSend({'status': 'ok'}, data)
             
             
             
+         elif(command == 'get_scripts_list'):
+            scripts = list()
+            try:
+               scripts = s.pcilib.get_scripts_list()
+            except Exception as e:
+               s.error(str(e), data) 
+               return
+
+            #Success! Create and send reply
+            s.wrapMessageAndSend({'status': 'ok', 'scripts': scripts}, data)
+         
+         
+         
+         elif(command == 'run_script'):
+            #check required arguments
+            if not 'script_name' in data:
+               s.error('message doesnt contains "script_name" field, '
+                       'which is required for "run_script" command', data)
+               return
+            #parse command arguments and convert them to string
+            script_name = str(data.get('script_name'))
+            value = data.get('value', None)
+            
+            out = None
+            try:
+               out = s.pcilib.run_script(script_name, value)
+            except Exception as e:
+               s.error(str(e), data) 
+               return
+
+            #Success! Create and send reply
+            if(type(out) == bytearray or type(out) == bytes):
+               s.send_response(200)
+               s.send_header('content-disposition', 'inline; filename=value')
+               s.send_header('content-type', 'application/octet-stream')
+               s.end_headers()
+               s.wfile.write(out)
+            else:
+               s.wrapMessageAndSend({'status': 'ok', 'value': out}, data)
+            
+            
+            
          #elif(command == 'lock_global'):
          #   #check if global_lock already setted by server
-         #   print 'aaa'
-         #   if PcilibServerHandler.lock_global:
-         #
-         #      s.error('global lock already setted by this server', data)
-         #      return
-         #      
          #   try:
-         #      pcilib.lock_global()
+         #      s.pcilib.lock_global()
          #   except Exception as e:
          #      s.error(str(e), data)
          #      return
          #   
-         #   PcilibServerHandler.lock_global = 1
-         #   
          #   #Success! Create and send reply
          #   s.wrapMessageAndSend({'status': 'ok'}, data)
             
@@ -341,34 +370,29 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
          
          #elif(command == 'unlock_global'):
          #   try:
-         #      pcilib.unlock_global()
+         #      s.pcilib.unlock_global()
          #   except Exception as e:
          #      s.error(str(e), data)
          #      return
          #   
-         #   PcilibServerHandler.lock_global = 0
-         #   
          #   #Success! Create and send reply
          #   s.wrapMessageAndSend({'status': 'ok'}, data)
          
-         
-            	
+      
          else:
-		    s.error('command "' + command + '" undefined', data)
-		    return
+            s.error('command "' + command + '" undefined', data)
+            return
       else:
-		  s.error('message doesnt contains "command" field, which is required', data)
-		  return
-		  
-       
-      #print str(s.headers['content-type'])
-      #print post_data['some']
+         s.error('message doesnt contains "command" field, which is required', data)
+         return
+        
+        
       
-   #"""open device context """
+   #open device context 
    #def openPcilibInstance(s, device, model):
-   #   pcilib = pcipywrap.create_pcilib_instance(device, model)
+   #   s.pcilib = pcipywrap.create_pcilib_instance(device, model)
          
-   """Send help message"""
+   #Send help message
    def help(s, received_message = None):
       usage = str('Usage:\n'
       '  Server receive commands via http GET with json packet.\n'
@@ -446,11 +470,27 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
       '      lock_id: - lock id\n'
       '\n'
       
+      '  command: get_scripts_list - Get aviable scripts with description\n'
+      '\n'
+      
+      '  command: run_script - Run specified script\n'
+      '    required fields\n'
+      '      script_name: - script name (without extension)\n'
+      '      value: - input value in json format\n'
+      '\n'
+      
       '\n')
-      out = {'status': 'ok', 'usage' : usage}
-      s.wrapMessageAndSend(out, received_message)
+      
+      #send help as plain text
+      s.send_response(200)
+      s.send_header('content-type', 'text/plain')
+      s.end_headers()
+      if sys.version_info >= (3,0):
+         s.wfile.write(bytes(usage, 'UTF-8'))
+      else:
+         s.wfile.write(usage)
 
-   """Send error message with text description"""     
+   #Send error message with text description    
    def error(s, info, received_message = None):
       out = dict()
       
@@ -465,8 +505,21 @@ class PcilibServerHandler(BaseHTTPRequestHandler):
       s.end_headers()
       if not received_message is None:
          message['received_message'] = received_message
-      message['thread'] = threading.currentThread().getName()
-      s.wfile.write(json.dumps(message))
+      if sys.version_info >= (3,0):
+         s.wfile.write(bytes(json.dumps(message), 'UTF-8'))
+      else:
+         s.wfile.write(json.dumps(message))
+      
+      
+class ApiServer(MultiThreadedHTTPServer):
+   def __init__(self, device='/dev/fpga0', model=None, adress=('0.0.0.0', 9000)):
+      #redirect logs to exeption
+      pcilib.redirect_logs_to_exeption()
+      #pass Pcipywrap to to server handler
+      self.lib = pcilib.pcilib(device, model)
+      def handler(*args):
+         PcilibServerHandler(self.lib, *args)
+      MultiThreadedHTTPServer.__init__(self, adress, handler)
 
 if __name__ == '__main__':
    
@@ -481,59 +534,24 @@ if __name__ == '__main__':
    parser.add_option("-m", "--model",  action="store",
                      type="string", dest="model", default=None,
                      help="Memory model (autodetected)")
+
    opts = parser.parse_args()[0]
    
-   HOST_NAME = ''
+   HOST_NAME = '0.0.0.0'
    PORT_NUMBER = opts.port
    MODEL = opts.model
    DEVICE = opts.device
    
-   
-   
-   #Set enviroment variables, if it not setted already
-   if not 'APP_PATH' in os.environ:
-      APP_PATH = ''
-      file_dir = os.path.dirname(os.path.abspath(__file__))
-      APP_PATH = str(os.path.abspath(file_dir + '/../..'))
-      os.environ["APP_PATH"] = APP_PATH
-
-   if not 'PCILIB_MODEL_DIR' in os.environ:   
-      os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml"
-      
-   if not 'LD_LIBRARY_PATH' in os.environ: 
-      os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib"
-   
-   
-   
-   #redirect logs to exeption
-   pcipywrap.__redirect_logs_to_exeption()
-   
-   #pass Pcipywrap to to server handler
-   global pcilib
-   pcilib = pcipywrap.Pcipywrap(DEVICE, MODEL)
-   #def handler(*args):
-   #   PcilibServerHandler(lib, *args)
-   
    #start server
-   httpd = MultiThreadedHTTPServer((HOST_NAME, PORT_NUMBER), PcilibServerHandler)
+   httpd = ApiServer(DEVICE, MODEL, (HOST_NAME, PORT_NUMBER))
+   
+   print(time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER))
    
-   print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
    try:
       httpd.serve_forever()
    except KeyboardInterrupt:
-      #unlocking global lock
-      if PcilibServerHandler.lock_global:
-         lib.unlock_global()
-         PcilibServerHandler.lock_global = False
-         
-      #delete created locks
-      for lock in PcilibServerHandler.locks:
-         lib.unlock(lock)
-      del PcilibServerHandler.locks[:]
       pass
       
-      
-      
-      
    httpd.server_close()
-   print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)
+   
+   print(time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER))

+ 231 - 0
pyserver/html_server.py

@@ -0,0 +1,231 @@
+import json
+
+from optparse import OptionParser, OptionGroup
+from multiprocessing import Process
+
+import requests
+from api_server import ApiServer
+
+#import flask elements
+from flask import render_template
+from flask import Flask
+from flask import request
+from flask import url_for
+from flask import redirect
+from flask import send_from_directory
+from flask import make_response
+
+app = Flask(__name__)
+api_server_port = 9000
+api_server_host = '0.0.0.0'
+
+@app.route("/json/<command>")
+def process_json_command(command):
+   headers = {'content-type': 'application/json'}
+   message = {'command': command}
+   
+   for arg in request.args:
+      message[arg] = request.args[arg]
+      
+   r = 0;
+   try:
+      r = requests.get('http://' + api_server_host + ':' + str(api_server_port),
+                       data=json.dumps(message),
+                       headers=headers)
+   except Exception as e:
+      return str(json.dumps({'status':'error', 'description': e}))
+   
+   #application/octet-stream
+   response = make_response(r.content)
+   for header in r.headers:
+      response.headers[header] = r.headers[header]
+      
+   return response
+
+#html api
+@app.route('/register_info')
+def get_register_info():
+   #get parameters
+   name = request.args.get('name')
+   bank = request.args.get('bank')
+   
+   #load register info
+   reg_info = 0
+   value = dict()
+   try:
+      r = requests.get(url_for('process_json_command', 
+                               command = 'get_register_info',
+                               bank = bank,
+                               reg = name, _external = True))
+      if(r.json().get('status') == 'error'):
+         return 'Error: ' + r.json()['description']
+         
+      reg_info = r.json()['register']
+      
+      #get register value
+      r = requests.get(url_for('process_json_command', 
+                               command = 'read_register',
+                               bank = bank,
+                               reg = name, _external = True))
+      if(r.json().get('status') == 'error'):
+         return 'Error: ' + r.json()['description']
+         
+      value[name] = r.json()['value']
+   except Exception as e:
+      return str(e)
+   
+   return render_template('register_info.html',
+                          register=reg_info,
+                          value=value)
+                             
+@app.route("/registers_list")
+def get_registers_list():
+   #get parameters
+   bank = request.args.get('bank')
+   if not bank is None:
+      bank = str(bank)
+   
+   #load registers list
+   reg_list = []
+   try:
+      r = requests.get(url_for('process_json_command', 
+                               command = 'get_registers_list',
+                               bank = bank, _external = True))
+      if(r.json().get('status') == 'error'):
+         return 'Error: ' + r.json()['description']
+      reg_list = r.json()['registers']
+   except Exception as e:
+      return str(e)
+   
+   #get register values
+   value = dict()
+   for reg in reg_list:
+      try:
+         r = requests.get(url_for('process_json_command', 
+                                  command = 'read_register',
+                                  bank = str(reg['bank']), 
+                                  reg = str(reg['name']), _external = True))
+         if(r.json().get('status') == 'error'):
+            value[reg['name']] = 'Error: ' + r.json()['description']
+         else:
+            value[reg['name']] = r.json()['value']
+         
+      except Exception as e:
+         value[reg['name']] = 'Error: ' + str(e)
+
+   #render result
+   return render_template('registers_list.html',
+                          registers = reg_list,
+                          render_template = render_template,
+                          value = value
+                         )
+
+@app.route("/property_info")
+def get_property_list():
+   #get parameters
+   branch = request.args.get('branch')
+   if not branch is None:
+      branch = str(branch)
+   
+   #get properties info
+   prop_info = 0  
+   try:
+      r = requests.get(url_for('process_json_command', 
+                               command = 'get_property_list',
+                               branch = branch, _external = True))
+                               
+      if(r.json().get('status') == 'error'):
+         return 'Error: ' + r.json()['description']
+         
+      prop_info = r.json()['properties']
+      
+   except Exception as e:
+      return str(e)
+   
+   value = dict()
+   for prop in prop_info:
+      try:
+         path = prop['path']
+         r = requests.get(url_for('process_json_command', 
+                                  command = 'get_property',
+                                  prop = path, _external = True))
+         if(r.json().get('status') == 'error'):
+            value[path] = 'Error: ' + r.json()['description']
+         else:   
+            value[path] = r.json()['value']
+            
+      except Exception as e:
+         value[path] = str(e)
+
+   return render_template('property_info.html',
+                          value = value,
+                          branch = branch,
+                          properties = prop_info,
+                          json = json
+                         )
+                         
+@app.route("/")
+def greet():
+   return render_template('base.html',
+                          device = device,
+                          model = model)
+
+if __name__ == "__main__":
+   #parse command line options
+   parser = OptionParser()
+   parser.add_option("-p", "--port",  action="store",
+                     type="int", dest="port", default=5000,
+                     help="Set server port (5000)")
+                     
+   pcilib_group = OptionGroup(parser, "Api server",
+                              "Api server options group")
+   pcilib_group.add_option("-e", "--external",  action="store_true",
+                           dest="external_api_server", 
+                           default=False,
+                           help="Dont start own api server. Use external"
+                                " server instead");                     
+   pcilib_group.add_option("--api-server-host", action="store",
+                           type="string", dest="api_server_host",
+                           default='0.0.0.0',
+                           help="Api server ip adress (0.0.0.0)")
+   pcilib_group.add_option("--api-server-port", action="store",
+                           type="int", dest="api_server_port",
+                           default=9000,
+                           help="Api server port (9000)")
+   pcilib_group.add_option("-d", "--device",  action="store",
+                           type="string", dest="device", 
+                           default=str('/dev/fpga0'),
+                           help="FPGA device (/dev/fpga0)")
+   pcilib_group.add_option("-m", "--model",  action="store",
+                           type="string", dest="model", default=None,
+                           help="Memory model (autodetected)")
+                       
+   parser.add_option_group(pcilib_group)
+                     
+   opts = parser.parse_args()[0]
+   
+   HOST_NAME = '0.0.0.0'
+   PORT_NUMBER = opts.port
+   
+   device = opts.device
+   model = opts.model
+   
+   #start api server in separate process
+   api_server_host = opts.api_server_host
+   api_server_port = opts.api_server_port
+   if(not opts.external_api_server):
+      api_server = ApiServer(device, model, (api_server_host, api_server_port))
+      def serve_forever(server):
+         try:
+            server.serve_forever()
+         except KeyboardInterrupt:
+            pass
+      
+      Process(target=serve_forever, args=(api_server,)).start()
+   
+   #start Flask html server
+   app.run(host = HOST_NAME, 
+           port = PORT_NUMBER,
+           threaded=True,
+           #debug=True
+         )

+ 10 - 0
pyserver/scripts/test_script.py

@@ -0,0 +1,10 @@
+import sys
+if sys.version_info >= (3,0):
+   import binascii
+   
+def run(ctx, inpt):
+   if sys.version_info >= (3,0):
+      return binascii.a2b_uu('111')
+   else:
+      return bytearray('111')
+   

+ 4 - 0
pyserver/scripts/test_script2.py

@@ -0,0 +1,4 @@
+description='this is a test script'
+
+def run(ctx, inpt):
+   return ctx.get_registers_list();

+ 46 - 0
pyserver/static/base.css

@@ -0,0 +1,46 @@
+.tabs > div, .tabs > input { display: none; }
+
+.tabs label {
+   padding: 5px;
+   border: 1px solid #aaa;
+   line-height: 28px;
+   cursor: pointer;
+   position: relative;
+   bottom: 1px;
+   background: #fff;
+}
+
+.tabs input[type="radio"]:checked + label { border-bottom: 2px solid #fff; }
+
+.tabs > input:nth-of-type(1):checked ~ div:nth-of-type(1),
+.tabs > input:nth-of-type(2):checked ~ div:nth-of-type(2) {
+   display: block; 
+   padding: 5px; 
+   border: 
+   1px solid #aaa;
+}
+.tree {
+   height: 85vh;
+   padding: 5px;
+   border: 1px solid #aaa;
+   line-height: 28px;
+   cursor: pointer;
+   position: relative;
+   bottom: 1px;
+   background: #fff;
+   overflow:auto;
+}
+
+.infoTable {
+   padding: 2px;
+   
+   border: 1px solid #aaa;
+   line-height: 28px;
+   cursor: pointer;
+   position: relative;
+   background: #fff;
+   overflow:auto;
+   bottom: 1px;
+   
+   text-align: left;
+}

+ 4 - 0
pyserver/static/check_err.js

@@ -0,0 +1,4 @@
+function checkError(json) {
+   if(json.status === 'error')
+      alert('Error: ' + json.description)
+} 

+ 0 - 0
pywrap/static/codebase/dhtmlx.css → pyserver/static/codebase/dhtmlx.css


+ 0 - 0
pywrap/static/codebase/dhtmlx.js → pyserver/static/codebase/dhtmlx.js


+ 0 - 0
pywrap/static/codebase/dhtmlx_deprecated.js → pyserver/static/codebase/dhtmlx_deprecated.js


+ 0 - 0
pywrap/static/codebase/ext/dhxupload.xap → pyserver/static/codebase/ext/dhxupload.xap


+ 0 - 0
pywrap/static/codebase/ext/swfobject.js → pyserver/static/codebase/ext/swfobject.js


+ 0 - 0
pywrap/static/codebase/ext/uploader.swf → pyserver/static/codebase/ext/uploader.swf


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/blank.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/blank.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/but_cut.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/but_cut.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/folderClosed.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/folderClosed.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/folderOpen.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/folderOpen.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/iconCheckAll.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckAll.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/iconCheckDis.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckDis.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/iconCheckGray.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/iconCheckGray.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/iconUncheckAll.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/iconUncheckAll.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/iconUncheckDis.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/iconUncheckDis.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/leaf.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/leaf.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line1.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line1.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line1_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line1_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line2.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line2.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line2_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line2_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line3.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line3.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line3_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line3_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line4.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line4.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/line4_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/line4_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/lock.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/lock.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus1.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus1.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus2.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus2.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus2_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus2_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus3.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus3.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus3_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus3_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus4.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus4.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus4_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus4_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus5.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus5.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/minus5_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/minus5_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus1.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus1.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus2.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus2.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus2_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus2_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus3.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus3.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus3_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus3_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus4.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus4.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus4_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus4_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus5.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus5.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/plus5_rtl.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/plus5_rtl.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/radio_off.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/radio_off.gif


+ 0 - 0
pywrap/static/codebase/imgs/dhxtree_skyblue/radio_on.gif → pyserver/static/codebase/imgs/dhxtree_skyblue/radio_on.gif


+ 0 - 0
pywrap/static/codebase/thirdparty/excanvas/AUTHORS → pyserver/static/codebase/thirdparty/excanvas/AUTHORS


+ 0 - 0
pywrap/static/codebase/thirdparty/excanvas/COPYING → pyserver/static/codebase/thirdparty/excanvas/COPYING


+ 0 - 0
pywrap/static/codebase/thirdparty/excanvas/README → pyserver/static/codebase/thirdparty/excanvas/README


+ 0 - 0
pywrap/static/codebase/thirdparty/excanvas/excanvas.js → pyserver/static/codebase/thirdparty/excanvas/excanvas.js


+ 0 - 0
pywrap/static/jquery-2.2.1.js → pyserver/static/jquery-2.2.1.js


+ 194 - 0
pyserver/templates/base.html

@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>{% block title %}Device {{ device }}{% endblock %}</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+	<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+	<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='codebase/dhtmlx.css') }}"/>
+   <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='base.css') }}"/>
+   <script type=text/javascript src="{{ url_for('static', filename='jquery-2.2.1.js') }}"></script>
+	<script src="{{ url_for('static', filename='codebase/dhtmlx.js') }}"></script>
+   <script src="{{ url_for('static', filename='check_err.js') }}"></script>
+	<script>
+      var propsTree
+      function createPropertyTree(branch, id) {
+         
+         function getPropertyItemsOnLevel(branch, id) {
+            var pathToProperties = "{{ url_for('process_json_command', command = 'get_property_list') }}"
+            var completePath = pathToProperties + '?branch=' + branch
+            
+            $.getJSON(completePath, 
+                      function(json) {
+                           checkError(json)
+                           parsePropertyItems(json, branch, id)
+                         });
+         }
+         
+         function parsePropertyItems(json, branch, id) {
+            
+            checkError(json)
+            json = json.properties
+            
+            function loadPropertyInfo(branch) {
+               
+               var pathToProperties = "{{ url_for('get_property_list') }}"
+               var completePath = pathToProperties + '?branch=' + branch
+               
+               $("#prop_info_place").load(completePath)
+            }
+            
+            
+            function setPropertyField(id, name, branch) {
+               
+               var func = function(){loadPropertyInfo(branch)}
+               propsTree.insertNewItem(id, branch,
+                                       name, 
+                                       func);
+               propsTree.closeAllItems()
+            }
+            
+            for(var i = 0; i < json.length; i++) {
+               
+               setPropertyField(id, json[i].name, json[i].path)
+               if(json[i].flags.indexOf("childs") != -1)
+                  getPropertyItemsOnLevel(json[i].path, json[i].path)
+            }  
+         }
+         
+         getPropertyItemsOnLevel(branch, id)
+      }
+      
+      var regTree
+      function createRegistersList() {
+         function parseJsonRegisterList(json) {
+            checkError(json)
+            json = json.registers
+            
+            function loadRegistersList(bank) {
+               var pathToGetRegisterList = "{{ url_for('get_registers_list') }}"
+               var completePath = pathToGetRegisterList + '?bank=' + bank
+
+               $("#reg_info_place").load(completePath)
+            }
+
+            function loadRegisterInfo(bank, name) {
+               var pathToGetRegister = "{{ url_for('get_register_info') }}"
+               var completePath = pathToGetRegister + '?bank=' + bank +
+                              '&name=' + name
+
+               $("#reg_info_place").load(completePath)
+            }
+
+            function setRegisterField(id, bank, name) {
+               
+               var itemId = bank + "_" + name
+               var func = function(){loadRegisterInfo(bank, name)}
+               
+               regTree.insertNewItem(id, itemId, name, func)
+               regTree.closeAllItems()
+            }
+            
+            function setbankField(bank) {
+               
+               var func = function(){loadRegistersList(bank)}
+               regTree.insertNewItem(0, bank, bank, func);
+               regTree.closeAllItems()
+            }
+            
+            checkError(json)
+            if(json.lenght <= 0)
+               return
+            
+            //sort registers by bank
+            function compareRegistersByBank(a,b) {
+               if (a.bank < b.bank)
+                  return -1;
+               else if (a.bank > b.bank)
+                  return 1;
+               else 
+                  return 0;
+            }
+            json.sort(compareRegistersByBank)
+            
+            
+            //create bank dirs
+            var curBankName = json[0].bank
+            var created = 0
+            for(var i = 0; i < json.length; i++) {
+               
+               //create new bank tab if it has not created already
+               if(json[i].bank != curBankName) {
+                  curBankName = json[i].bank
+                  created = 0
+               }
+               
+               if(!created) {
+                  setbankField(json[i].bank )
+                  created = 1
+               }
+               
+               
+               //insert register info to bank
+               
+               setRegisterField(json[i].bank, json[i].bank, json[i].name)
+            }
+         }
+         
+         //get registers json list
+         var getRegistersListPath = "{{ url_for('process_json_command', command = 'get_registers_list') }}" 
+         $.getJSON(getRegistersListPath, parseJsonRegisterList);
+      }
+      
+		function doOnLoad()
+      {
+			propsTree = new dhtmlXTreeObject("treeboxbox_tree","100%","100%",0);
+			propsTree.setImagePath("{{ url_for('static', filename='codebase/imgs/dhxtree_skyblue/') }}");
+         //generating properties list
+         createPropertyTree('', 0)
+         
+			regTree = new dhtmlXTreeObject("treeboxbox_tree2","100%","100%",0,0,0,0,'SELECT')
+			regTree.setImagePath("{{ url_for('static', filename='codebase/imgs/dhxtree_skyblue/') }}");
+         createRegistersList()
+		}
+	</script>
+</head>
+<body onload="doOnLoad()">
+	{% block info %}
+      <div class="block1" >
+         <h2>Device {{ device }} model={{ model }} control page </h2>
+      </div>
+   {% endblock %}
+   
+   <div class="tabs">
+      <input type="radio" name="current" checked="checked" id="props_id"/>
+      <label for="props_id">Properties</label>
+      <input type="radio" name="current" id="labels_id"/>
+      <label for="labels_id">Registers</label>
+      <div>
+         <table>
+            <tr>
+               <td valign="top">
+                  <div id="treeboxbox_tree" class = "tree"></div>
+               </td>
+               <td valign="top" id="prop_info_place" />
+            </tr>
+         </table>         
+      </div>
+      <div>
+         <table>
+            <tr>
+               <td valign="top">
+                  <div id="treeboxbox_tree2" class="tree"></div>
+               </td>
+               <td valign="top" id="reg_info_place" />
+            </tr>
+         </table>
+      </div>
+   </div>
+   {% block content %}
+   {% endblock %}
+    <div class="block1" >
+      <a href="{{ url_for('process_json_command', command='help') }}">Json API usage</a>
+    </div>
+</body>
+</html>

+ 91 - 0
pyserver/templates/property_info.html

@@ -0,0 +1,91 @@
+{% block content %}
+
+{% if standalone %}
+<script src="{{ url_for('static', filename='codebase/dhtmlx.js') }}"></script>
+<script src="{{ url_for('static', filename='check_err.js') }}"></script>
+{% endif %}
+
+<script>
+   function updateProperty(prop) {
+      var pathToGetProperty = "{{ url_for('process_json_command', command = 'get_property') }}"
+      var completePath = pathToGetProperty + '?prop=' + prop
+      
+      $.getJSON(completePath, function(json){
+                  checkError(json)
+                  var valFieldId = "#set_val_" + prop.split('/').join("_")
+                  $(valFieldId).val(json.value)
+               })
+   }
+   
+   function setProperty(prop)
+   {
+      var value = document.getElementById("set_val_" + prop.split('/').join("_")).value;
+      if(value == "")
+         return
+      
+      var pathToGetProperty = "{{ url_for('process_json_command', command = 'set_property') }}"
+      var completePath = pathToGetProperty + '?prop=' + prop +
+                     '&value=' + value;
+                        
+      $.getJSON(completePath, 
+                function(json) {
+                   checkError(json)
+                   updateProperty(prop)
+                })
+   };
+</script>
+
+<table class="infoTable">
+   <tr class="infoTable">
+      <td class="infoTable">Name</td>
+      <td class="infoTable">Description</td>
+      <td class="infoTable">Value</td>
+      <td class="infoTable">Mode</td>
+      <td class="infoTable">Type</td>
+      <td class="infoTable">Unit</td>
+      <td class="infoTable">Path</td>
+   </tr>
+   {% for property in properties %}
+      <tr class="infoTable">
+         <td class="infoTable">{{ property.name }}</td>
+         <td class="infoTable">
+         {% if 'description' in property %}
+             {{ property.description }}
+         {% endif %}
+         </td>
+         <td class="infoTable">
+            <table>
+               {% if 'R' in property.mode %}
+                  <tr>
+                     <td> 
+                           <input type="text"
+                                  name="set_val_{{ property.path.replace('/', '_') }}"
+                                  id="set_val_{{ property.path.replace('/', '_') }}"
+                                  value="{{ value[property.path] }}" />
+                     </td>
+                     {% if 'W' in property.mode %}
+                     <td> 
+                           <input type="button" value="set" style="width:100%;height:100%" onclick="setProperty('{{ property.path }}')">
+                     </td>
+                     {% endif %}
+                     <td> 
+                        <input type="button" value="update" style="width:100%;height:100%" onclick="updateProperty('{{ property.path }}')">
+                     </td>
+                  </tr>
+               {% endif %}
+            </table>
+         </td>
+         <td class="infoTable">
+            <ul>
+            {% for m in property.mode %}
+               {{ m + ';  '}}
+            {% endfor %}
+            </ul>
+         </td>
+         <td class="infoTable"> {{ property.type }} </td>
+         <td class="infoTable"> {{ property.unit }} </td>
+         <td class="infoTable"> {{ property.path }} </td>
+      </tr>
+   {% endfor %}
+</table>
+{% endblock %}

+ 9 - 0
pyserver/templates/register_info.html

@@ -0,0 +1,9 @@
+{% block content %}
+
+{% include 'registers/table_scripts.html' %}
+
+<table class="infoTable">
+   {% include 'registers/table_header.html' %}
+   {% include 'registers/table_cell.html' %}
+</table>
+{% endblock %}

+ 100 - 0
pyserver/templates/registers/table_cell.html

@@ -0,0 +1,100 @@
+<tr class="infoTable">
+   <td class="infoTable"> {{ register.name }} </td>
+   {% if 'description' in register %}
+      <td class="infoTable"> {{ register.description }} </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+   <td class="infoTable">
+      <table>
+         {% if 'R' in register.mode %}
+         <tr class="infoTable">
+            <td> 
+                  <input type="text"
+                         name="set_val_box_{{ register.bank }}_{{ register.name }}"
+                         id="set_val_box_{{ register.bank }}_{{ register.name }}" 
+                         value="{{ value[register.name] }}" />
+            </td>
+            {% if 'W' in register.mode %}
+            <td> 
+               <input type="button" value="set"
+                      style="width:100%;height:100%" 
+                      onclick="writeRegister('{{ register.bank }}', '{{ register.name }}')">
+            </td>
+            {% endif %}
+            <td> 
+               <input type="button" value="update"
+                      style="width:100%;height:100%"
+                      onclick="updateRegister('{{ register.bank }}', '{{ register.name }}')">
+            </td>
+         </tr>
+         {% endif %}
+      </table>
+   </td>
+   <td class="infoTable">{{ register.defvalue }}</td>
+   <td class="infoTable">{{ register.bank }}</td>
+   <td class="infoTable">
+      <ul>
+      {% for m in register.mode %}
+         {{ m + ';  '}}
+      {% endfor %}
+      </ul>
+   </td>
+   {% if 'range' in register %}
+      <td class="infoTable">
+         <table>
+            <tr class="infoTable">
+               <td class="infoTable"> min </td>
+               <td class="infoTable"> max </td>
+            </tr>
+            <tr class="infoTable">
+               <td class="infoTable"> {{ register.range.min }} </td>
+               <td class="infoTable"> {{ register.range.max }} </td>
+            </tr>
+         </table>
+      </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+   {% if 'values' in register %}
+   <td class="infoTable">
+      <table>
+         <tr>
+         {% for v in register['values'] %}
+            <td>
+            <table>
+               {% if 'name' in v %}
+                  <tr class="infoTable">
+                     <td class="infoTable"> Name </td>
+                     <td class="infoTable"> {{v.name}} </td>
+                  </tr>
+               {% endif %}
+               {% if 'description' in v %}
+                  <tr class="infoTable">
+                     <td class="infoTable"> Description </td>
+                     <td class="infoTable"> {{ v.description }} </td>
+                  </tr>
+               {% endif %}
+               <tr class="infoTable">
+                  <td class="infoTable"> Min </td>
+                  <td class="infoTable"> {{ v.min }} </td>
+               </tr>
+               <tr class="infoTable">
+                  <td class="infoTable"> Max </td>
+                  <td class="infoTable"> {{ v.max }} </td>
+               </tr>
+               <tr class="infoTable">
+                  <td class="infoTable"> Value </td>
+                  <td class="infoTable"> {{ v.value }} </td>
+               </tr>
+            </table>
+            </td>
+         {% endfor %}
+         </tr>
+      </table>
+   </td>
+   {% else %}
+      <td class="infoTable">  </td>
+   {% endif %}
+</tr>
+

+ 10 - 0
pyserver/templates/registers/table_header.html

@@ -0,0 +1,10 @@
+<tr class="infoTable">
+      <td class="infoTable"> Name </td>
+      <td class="infoTable"> Description </td>
+      <td class="infoTable"> Value </td>
+      <td class="infoTable">Default value</td>
+      <td class="infoTable">Bank</td>
+      <td class="infoTable">Mode</td>
+      <td class="infoTable">Range</td>
+      <td class="infoTable">Values</td>
+</tr> 

+ 42 - 0
pyserver/templates/registers/table_scripts.html

@@ -0,0 +1,42 @@
+{% if standalone %}
+<script src="{{ url_for('static', filename='codebase/dhtmlx.js') }}"></script>
+<script src="{{ url_for('static', filename='check_err.js') }}"></script>
+{% endif %}
+
+<script>
+   /*
+   $("#set_val_box").keyup(function(event){
+    if(event.keyCode == 13){
+        $("#set_val_button").click();
+    }
+   });
+   */
+   
+   function updateRegister(bank, name) {
+      var pathToReadRegister = "{{ url_for('process_json_command', command = 'read_register') }}"
+      var completePath = pathToReadRegister + '?bank=' + bank +
+                     '&reg=' + name
+      
+      $.getJSON(completePath, function(json){
+                  checkError(json)
+                  $("#set_val_box_" + bank + "_" + name).val(json.value)
+               })
+   }
+   
+   function writeRegister(bank, name)
+   {
+      var value = document.getElementById("set_val_box_" + bank + "_" + name).value;
+      if(value == "")
+         return
+      
+      var pathToReadRegister = "{{ url_for('process_json_command', command = 'write_register') }}"
+      var completePath = pathToReadRegister + '?bank=' + bank +
+                     '&reg=' + name + '&value=' + value;
+                        
+      $.getJSON(completePath, 
+                function(json) {
+                   checkError(json)
+                   updateRegister(bank, name)
+                })
+   }; 
+</script> 

+ 12 - 0
pyserver/templates/registers_list.html

@@ -0,0 +1,12 @@
+{% block content %}
+{% include 'registers/table_scripts.html' %}
+
+<table class="infoTable">
+{% include 'registers/table_header.html' %}
+{% for register in registers %}
+   {% include 'registers/table_cell.html' %}
+{% endfor %}
+</table>
+{% endblock %}
+
+

+ 2 - 7
pywrap/CMakeLists.txt

@@ -17,15 +17,10 @@ set(CMAKE_SWIG_FLAGS "")
 swig_add_module(pcipywrap python pcipywrap.i pcipywrap.c)
 swig_link_libraries(pcipywrap ${PYTHON_LIBRARIES} pcilib)
 
-
 install(TARGETS ${SWIG_MODULE_pcipywrap_REAL_NAME} DESTINATION ${PYTHON_INSTALL_DIR})
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcipywrap.py DESTINATION ${PYTHON_INSTALL_DIR})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcilib.py DESTINATION ${PYTHON_INSTALL_DIR})
 
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
-    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/server.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_pcipywrap.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-
-    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/templates DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/static DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/html_server.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+   file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_pcilib.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 endif(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)

+ 0 - 197
pywrap/html_server.py

@@ -1,197 +0,0 @@
-import pcipywrap
-import json
-from optparse import OptionParser
-
-#import flask elements
-from flask import render_template
-from flask import Flask
-from flask import request
-from flask import url_for
-from flask import redirect
-from flask import send_from_directory
-
-app = Flask(__name__)
-pcilib = 0;
-device = '/dev/fpga0'
-model = 'test_pywrap'
-
-# property json api
-@app.route("/property_info_json")
-def get_property_list_json():
-   branch = request.args.get('branch')
-   if not branch is None:
-      branch = str(branch)
-   
-   prop_info = 0
-   try:
-      prop_info = pcilib.get_property_list(branch)
-      return json.dumps(prop_info)
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-
-@app.route('/get_property_json')
-def get_property_json():
-   prop = request.args.get('prop')
-
-   try:
-      val = pcilib.get_property(str(prop))
-      return json.dumps({'value': val})
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-      
-@app.route('/set_property_json')
-def set_property_json():
-   val = request.args.get('val')
-   prop = request.args.get('prop')
-
-   try:
-      pcilib.set_property(float(val), str(prop))
-      return json.dumps({'status': 'ok'})
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-      
-# register json api
-@app.route("/registers_list_json")
-def get_registers_list_json():
-   reg_list = 0
-   try:
-      reg_list = pcilib.get_registers_list()
-      return json.dumps(reg_list)
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-
-@app.route('/read_register_json')
-def read_register_json():
-   name = request.args.get('name')
-   bank = request.args.get('bank')
-   
-   try:
-      value = pcilib.read_register(str(name), str(bank))
-      return json.dumps({'value': value})
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-
-@app.route('/write_register_json')
-def write_register_json():
-   val = request.args.get('val')
-   name = request.args.get('name')
-   bank = request.args.get('bank')
-
-   try:
-      pcilib.write_register(float(val), str(name), str(bank))
-      return json.dumps({'status': 'ok'})
-   except Exception as e:
-      return json.dumps({'error': str(e)})
-
-#html api
-@app.route('/set_property')
-def set_property():
-   val = request.args.get('val')
-   prop = request.args.get('prop')
-
-   try:
-      pcilib.set_property(float(val), str(prop))
-      return redirect(url_for('get_property_list', branch=prop))
-   except Exception as e:
-      return str(e)
-   
-@app.route('/write_register')
-def write_register():
-   val = request.args.get('val')
-   name = request.args.get('name')
-   bank = request.args.get('bank')
-
-   try:
-      pcilib.write_register(float(val), str(name), str(bank))
-      return redirect(url_for('get_register_info', name=name, bank=bank))
-   except Exception as e:
-      return str(e)
-
-@app.route('/register_info')
-def get_register_info():
-   name = request.args.get('name')
-   bank = request.args.get('bank')
-   
-   reg_info = 0
-   value = 0
-   try:
-      reg_info = pcilib.get_register_info(str(name), str(bank))
-      value = pcilib.read_register(str(name), str(bank))
-   except Exception as e:
-      return str(e)
-   return render_template('register_info.html',
-                          register=reg_info,
-                          value=value)
-                             
-@app.route("/registers_list")
-def get_registers_list():
-   reg_list = 0
-   try:
-      reg_list = pcilib.get_registers_list()
-   except Exception as e:
-      return str(e)
-
-   return render_template('registers_list.html',
-                          registers=reg_list,
-                         )
-
-@app.route("/property_info")
-def get_property_list():
-   branch = request.args.get('branch')
-   if not branch is None:
-      branch = str(branch)
-   
-   prop_info = 0
-   try:
-      prop_info = pcilib.get_property_list(branch)
-   except Exception as e:
-      return str(e)
-   
-   value = -1
-   if (len(prop_info) == 1) and not ('childs' in (prop_info[0])['flags']):
-      try:
-         branch = (prop_info[0])['path']
-         value = pcilib.get_property(branch)
-      except Exception as e:
-         return str(e)
-
-   return render_template('property_info.html',
-                          value = value,
-                          branch = branch,
-                          properties = prop_info,
-                          json = json
-                         )
-                         
-@app.route("/")
-def greet():
-   return render_template('base.html',
-                          device = device,
-                          model = model)
-
-@app.route('/<path:path>')
-def send_file(path):
-    return send_from_directory('static', path)
-
-if __name__ == "__main__":
-   #parce command line options
-   parser = OptionParser()
-   parser.add_option("-p", "--port",  action="store",
-                     type="int", dest="port", default=5000,
-                     help="Set server port (5000)")
-   parser.add_option("-d", "--device",  action="store",
-                     type="string", dest="device", default=str('/dev/fpga0'),
-                     help="FPGA device (/dev/fpga0)")                     
-   parser.add_option("-m", "--model",  action="store",
-                     type="string", dest="model", default=None,
-                     help="Memory model (autodetected)")
-   opts = parser.parse_args()[0]
-   
-   HOST_NAME = '0.0.0.0'
-   PORT_NUMBER = opts.port
-   
-   device = opts.device
-   model = opts.model
-   
-   pcilib = pcipywrap.Pcipywrap(device, model)
-   pcipywrap.__redirect_logs_to_exeption()
-   app.run(host = HOST_NAME, port = PORT_NUMBER)

+ 38 - 0
pywrap/pcilib.py

@@ -0,0 +1,38 @@
+from pcipywrap import *
+import os
+import sys
+
+class pcilib(pcipywrap):
+   def __init__(s, *args):
+      pcipywrap.__init__(s, *args)
+      
+      #load scripts
+      scripts_dir = os.environ.get('PCILIB_SCRIPTS_DIR')
+      if scripts_dir:
+         scripts_dir_abs = os.path.abspath(scripts_dir)
+         if not scripts_dir_abs in sys.path:
+            sys.path.append(scripts_dir_abs)
+         
+         s.__scipts = dict()
+         for script in os.listdir(scripts_dir_abs):
+            if script.endswith('.py'):
+               script_module = os.path.splitext(script)[0]
+               __import__(script_module)
+               s.__scipts[script_module] = sys.modules[script_module]
+               
+               
+   def get_scripts_list(s):
+      scripts = []
+      for script in s.__scipts:
+         curr_script = dict()
+         curr_script['name'] = script
+         if 'description' in dir(s.__scipts[script]):
+            curr_script['description'] = s.__scipts[script].description
+         scripts.append(curr_script)
+      return scripts
+      
+      
+   def run_script(s, name, input_value):
+      if not name in s.__scipts:
+         raise Exception('Script ' + name +' has not loaded')
+      return s.__scipts[name].run(s, input_value)

+ 91 - 85
pywrap/pcipywrap.c

@@ -94,7 +94,7 @@ void set_python_exception(const char* msg, ...)
 }
 
 
-void __redirect_logs_to_exeption()
+void redirect_logs_to_exeption()
 {
     pcilib_set_logger(pcilib_get_log_level(),
                       pcilib_print_error_to_py,
@@ -128,12 +128,12 @@ void add_pcilib_value_to_dict(pcilib_t* ctx, PyObject* dict, pcilib_value_t* val
 
     if(py_val)
         pcilib_pydict_set_item(dict,
-                               PyString_FromString(name),
+                               PyUnicode_FromString(name),
                                py_val);
     else
         pcilib_pydict_set_item(dict,
-                               PyString_FromString("defvalue"),
-                               PyString_FromString("invalid"));
+                               PyUnicode_FromString("defvalue"),
+                               PyUnicode_FromString("invalid"));
 }
 
 PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_property_info_t listItem)
@@ -142,18 +142,18 @@ PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_proper
 
     if(listItem.name)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("name"),
-                               PyString_FromString(listItem.name));
+                               PyUnicode_FromString("name"),
+                               PyUnicode_FromString(listItem.name));
 
     if(listItem.description)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("description"),
-                               PyString_FromString(listItem.description));
+                               PyUnicode_FromString("description"),
+                               PyUnicode_FromString(listItem.description));
 
     if(listItem.path)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("path"),
-                               PyString_FromString(listItem.path));
+                               PyUnicode_FromString("path"),
+                               PyUnicode_FromString(listItem.path));
 
     //serialize types
     const char* type = "invalid";
@@ -175,40 +175,40 @@ PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_proper
         break;
     }
     pcilib_pydict_set_item(pylistItem,
-                           PyString_FromString("type"),
-                           PyString_FromString(type));
+                           PyUnicode_FromString("type"),
+                           PyUnicode_FromString(type));
 
 
     //serialize modes
     PyObject* modes = PyList_New(0);
 
     if((listItem.mode & PCILIB_ACCESS_R ) == PCILIB_REGISTER_R)
-        pcilib_pylist_append(modes, PyString_FromString("R"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("R"));
     if((listItem.mode & PCILIB_ACCESS_W ) == PCILIB_REGISTER_W)
-        pcilib_pylist_append(modes, PyString_FromString("W"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("W"));
     if((listItem.mode & PCILIB_ACCESS_RW ) == PCILIB_REGISTER_RW)
-        pcilib_pylist_append(modes, PyString_FromString("RW"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("RW"));
     if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
-        pcilib_pylist_append(modes, PyString_FromString("NO_CHK"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("NO_CHK"));
 
     pcilib_pydict_set_item(pylistItem,
-                           PyString_FromString("mode"),
+                           PyUnicode_FromString("mode"),
                            modes);
 
     //serialize flags
     PyObject* flags = PyList_New(0);
 
     if((listItem.flags & PCILIB_LIST_FLAG_CHILDS ) == PCILIB_LIST_FLAG_CHILDS)
-        pcilib_pylist_append(flags, PyString_FromString("childs"));
+        pcilib_pylist_append(flags, PyUnicode_FromString("childs"));
 
     pcilib_pydict_set_item(pylistItem,
-                           PyString_FromString("flags"),
+                           PyUnicode_FromString("flags"),
                            flags);
 
     if(listItem.unit)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("unit"),
-                               PyString_FromString(listItem.unit));
+                               PyUnicode_FromString("unit"),
+                               PyUnicode_FromString(listItem.unit));
 
     return pylistItem;
 }
@@ -219,42 +219,42 @@ PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_regist
 
     if(listItem.name)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("name"),
-                               PyString_FromString(listItem.name));
+                               PyUnicode_FromString("name"),
+                               PyUnicode_FromString(listItem.name));
 
     if(listItem.description)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("description"),
-                               PyString_FromString(listItem.description));
+                               PyUnicode_FromString("description"),
+                               PyUnicode_FromString(listItem.description));
 
     if(listItem.bank)
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("bank"),
-                               PyString_FromString(listItem.bank));
+                               PyUnicode_FromString("bank"),
+                               PyUnicode_FromString(listItem.bank));
 
 
     //serialize modes
     PyObject* modes = PyList_New(0);
 
     if((listItem.mode & PCILIB_REGISTER_R) == PCILIB_REGISTER_R)
-        pcilib_pylist_append(modes, PyString_FromString("R"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("R"));
     if((listItem.mode & PCILIB_REGISTER_W) == PCILIB_REGISTER_W)
-        pcilib_pylist_append(modes, PyString_FromString("W"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("W"));
     if((listItem.mode & PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW)
-        pcilib_pylist_append(modes, PyString_FromString("RW"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("RW"));
     if((listItem.mode & PCILIB_REGISTER_W1C) == PCILIB_REGISTER_W1C)
-        pcilib_pylist_append(modes, PyString_FromString("W1C"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("W1C"));
     if((listItem.mode & PCILIB_REGISTER_RW1C) == PCILIB_REGISTER_RW1C)
-        pcilib_pylist_append(modes, PyString_FromString("RW1C"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("RW1C"));
     if((listItem.mode & PCILIB_REGISTER_W1I) == PCILIB_REGISTER_W1I)
-        pcilib_pylist_append(modes, PyString_FromString("W1I"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("W1I"));
     if((listItem.mode & PCILIB_REGISTER_RW1I) == PCILIB_REGISTER_RW1I)
-        pcilib_pylist_append(modes, PyString_FromString("RW1I"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("RW1I"));
     if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
-        pcilib_pylist_append(modes, PyString_FromString("NO_CHK"));
+        pcilib_pylist_append(modes, PyUnicode_FromString("NO_CHK"));
 
     pcilib_pydict_set_item(pylistItem,
-                           PyString_FromString("mode"),
+                           PyUnicode_FromString("mode"),
                            modes);
 
     pcilib_value_t defval = {0};
@@ -273,7 +273,7 @@ PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_regist
         add_pcilib_value_to_dict(ctx, range, &minval, "min");
         add_pcilib_value_to_dict(ctx, range, &maxval, "max");
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("range"),
+                               PyUnicode_FromString("range"),
                                range);
     }
 
@@ -301,20 +301,20 @@ PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_regist
 
             if(listItem.values[j].name)
                 pcilib_pydict_set_item(valuesItem,
-                                       PyString_FromString("name"),
-                                       PyString_FromString(listItem.values[j].name));
+                                       PyUnicode_FromString("name"),
+                                       PyUnicode_FromString(listItem.values[j].name));
             if(listItem.values[j].description)
             {
                 pcilib_pydict_set_item(valuesItem,
-                                       PyString_FromString("description"),
-                                       PyString_FromString(listItem.values[j].description));
+                                       PyUnicode_FromString("description"),
+                                       PyUnicode_FromString(listItem.values[j].description));
 
             }
             pcilib_pylist_append(values, valuesItem);
         }
 
         pcilib_pydict_set_item(pylistItem,
-                               PyString_FromString("values"),
+                               PyUnicode_FromString("values"),
                                values);
     }
 
@@ -322,7 +322,7 @@ PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_regist
 
 }
 
-Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model)
+pcipywrap *new_pcipywrap(const char* fpga_device, const char* model)
 {
     //opening device
     pcilib_t* ctx = pcilib_open(fpga_device, model);
@@ -331,36 +331,37 @@ Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model)
         set_python_exception("Failed pcilib_open(%s, %s)", fpga_device, model);
         return NULL;
     }
-    Pcipywrap *self;
-    self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+    pcipywrap *self;
+    self = (pcipywrap *) malloc(sizeof(pcipywrap));
     self->shared = 0;
     self->ctx = ctx;
     return self;
 }
 
-Pcipywrap *create_Pcipywrap(PyObject* ctx)
+pcipywrap *create_pcipywrap(PyObject* ctx)
 {
-    if(!PyCObject_Check(ctx))
+    if(!PyCapsule_CheckExact(ctx))
     {
-        set_python_exception("Incorrect ctx type. Only PyCObject is allowed");
+        set_python_exception("Incorrect ctx type. Only PyCapsule is allowed");
         return NULL;
     }
 
-    Pcipywrap *self;
-    self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+    pcipywrap *self;
+    self = (pcipywrap *) malloc(sizeof(pcipywrap));
     self->shared = 1;
-    self->ctx = PyCObject_AsVoidPtr(ctx);
+    self->ctx = PyCapsule_GetPointer(ctx, PyCapsule_GetName(ctx));
+
     return self;
 }
 
-void delete_Pcipywrap(Pcipywrap *self) {
+void delete_pcipywrap(pcipywrap *self) {
     if(!self->shared)
         pcilib_close(self->ctx);
 
     free(self);
 }
 
-PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank)
+PyObject* pcipywrap_read_register(pcipywrap *self, const char *regname, const char *bank)
 {
     pcilib_value_t val = {0};
     pcilib_register_value_t reg_value;
@@ -384,7 +385,7 @@ PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const ch
     return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
 }
 
-PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank)
+PyObject* pcipywrap_write_register(pcipywrap *self, PyObject* val, const char *regname, const char *bank)
 {
     pcilib_value_t val_internal = {0};
     pcilib_register_value_t reg_value;
@@ -415,10 +416,10 @@ PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *r
         return NULL;
     }
 
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop)
+PyObject* pcipywrap_get_property(pcipywrap *self, const char *prop)
 {
     int err;
     pcilib_value_t val = {0};
@@ -434,7 +435,7 @@ PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop)
     return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
 }
 
-PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop)
+PyObject* pcipywrap_set_property(pcipywrap *self, PyObject* val, const char *prop)
 {
     int err;
 
@@ -453,25 +454,30 @@ PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *pro
         return NULL;
     }
 
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank)
+PyObject* pcipywrap_get_registers_list(pcipywrap *self, const char *bank)
 {
-    pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
-    PyObject* pyList = PyList_New(0);
-    for(int i = 0; i < ((pcilib_t*)self->ctx)->num_reg; i++)
-    {
-        //serialize item attributes
-        PyObject* pylistItem = pcilib_convert_register_info_to_pyobject(self->ctx, list[i]);
-        pcilib_pylist_append(pyList, pylistItem);
-        //Py_DECREF(pylistItem);
-    }
-    pcilib_free_register_info(self->ctx, list);
-    return pyList;
+   pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
+
+   if(!list) {
+      set_python_exception("pcilib_get_register_list return NULL");
+      return NULL;
+   }
+
+   PyObject* pyList = PyList_New(0);
+   for(int i = 0; list[i].name; i++)
+   {
+      //serialize item attributes
+      PyObject* pylistItem = pcilib_convert_register_info_to_pyobject(self->ctx, list[i]);
+      pcilib_pylist_append(pyList, pylistItem);
+   }
+   pcilib_free_register_info(self->ctx, list);
+   return pyList;
 }
 
-PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank)
+PyObject* pcipywrap_get_register_info(pcipywrap *self, const char* reg,const char *bank)
 {
     pcilib_register_info_t *info = pcilib_get_register_info(self->ctx, bank, reg, PCILIB_LIST_FLAGS_DEFAULT);
 
@@ -487,7 +493,7 @@ PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const cha
     return py_info;
 }
 
-PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch)
+PyObject* pcipywrap_get_property_list(pcipywrap *self, const char* branch)
 {
     pcilib_property_info_t *list = pcilib_get_property_list(self->ctx, branch, PCILIB_LIST_FLAGS_DEFAULT);
 
@@ -505,7 +511,7 @@ PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch)
     return pyList;
 }
 
-PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size)
+PyObject* pcipywrap_read_dma(pcipywrap *self, unsigned char dma, size_t size)
 {
     int err;
     void* buf = NULL;
@@ -526,7 +532,7 @@ PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size)
     return py_buf;
 }
 
-PyObject* Pcipywrap_lock_global(Pcipywrap *self)
+PyObject* pcipywrap_lock_global(pcipywrap *self)
 {
     int err;
 
@@ -537,19 +543,19 @@ PyObject* Pcipywrap_lock_global(Pcipywrap *self)
         return NULL;
     }
 
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
-void Pcipywrap_unlock_global(Pcipywrap *self)
+void pcipywrap_unlock_global(pcipywrap *self)
 {
     pcilib_unlock_global(self->ctx);
     return;
 }
 
-PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
-                                          PCILIB_LOCK_FLAGS_DEFAULT,
+                                          PCILIB_LOCK_FLAG_PERSISTENT,
                                           lock_id);
     if(!lock)
     {
@@ -565,13 +571,13 @@ PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id)
         return NULL;
     }
 
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
-                                          PCILIB_LOCK_FLAGS_DEFAULT,
+                                          PCILIB_LOCK_FLAG_PERSISTENT,
                                           lock_id);
     if(!lock)
     {
@@ -586,13 +592,13 @@ PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id)
         return NULL;
     }
 
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
-                                          PCILIB_LOCK_FLAGS_DEFAULT,
+                                          PCILIB_LOCK_FLAG_PERSISTENT,
                                           lock_id);
     if(!lock)
     {
@@ -601,7 +607,7 @@ PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id)
     }
 
     pcilib_unlock(lock);
-    return PyInt_FromLong((long)1);
+    return PyLong_FromLong((long)1);
 }
 
 

+ 19 - 19
pywrap/pcipywrap.h

@@ -8,7 +8,7 @@
 typedef struct {
     void* ctx;
     int shared;
-} Pcipywrap;
+} pcipywrap;
 
 /*!
  * \brief Redirect pcilib standart log stream to exeption text.
@@ -16,7 +16,7 @@ typedef struct {
  * After that, logger will write last error, and all accumulated errors
  * to Python exeption text
  */
-void __redirect_logs_to_exeption();
+void redirect_logs_to_exeption();
 
 /*!
  * \brief Wraps for pcilib_open function.
@@ -26,9 +26,9 @@ void __redirect_logs_to_exeption();
  */
 PyObject* create_pcilib_instance(const char *fpga_device, const char *model);
 
-Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model);
-Pcipywrap *create_Pcipywrap(PyObject* ctx);
-void delete_Pcipywrap(Pcipywrap *self);
+pcipywrap *new_pcipywrap(const char* fpga_device, const char* model);
+pcipywrap *create_pcipywrap(PyObject* ctx);
+void delete_pcipywrap(pcipywrap *self);
 
 /*!
  * \brief Reads register value. Wrap for pcilib_read_register function.
@@ -36,7 +36,7 @@ void delete_Pcipywrap(Pcipywrap *self);
  * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
  * \return register value, can be integer or float type; NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank);
+PyObject* pcipywrap_read_register(pcipywrap *self, const char *regname, const char *bank);
 
 /*!
  * \brief Writes value to register. Wrap for pcilib_write_register function.
@@ -45,14 +45,14 @@ PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const ch
  * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank);
+PyObject* pcipywrap_write_register(pcipywrap *self, PyObject* val, const char *regname, const char *bank);
 
 /*!
  * \brief Reads propety value. Wrap for pcilib_get_property function.
  * \param[in] prop property name (full name including path)
  * \return property value, can be integer or float type; NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop);
+PyObject* pcipywrap_get_property(pcipywrap *self, const char *prop);
 
 /*!
  * \brief Writes value to property. Wrap for pcilib_set_property function.
@@ -60,27 +60,27 @@ PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop);
  * \param[in] val Property value, that needs to be set. Can be int, float or string.
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop);
-PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank);
-PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank);
-PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch);
+PyObject* pcipywrap_set_property(pcipywrap *self, PyObject* val, const char *prop);
+PyObject* pcipywrap_get_registers_list(pcipywrap *self, const char *bank);
+PyObject* pcipywrap_get_register_info(pcipywrap *self, const char* reg,const char *bank);
+PyObject* pcipywrap_get_property_list(pcipywrap *self, const char* branch);
 
-PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size);
+PyObject* pcipywrap_read_dma(pcipywrap *self, unsigned char dma, size_t size);
 
-PyObject* Pcipywrap_lock_global(Pcipywrap *self);
-void Pcipywrap_unlock_global(Pcipywrap *self);
+PyObject* pcipywrap_lock_global(pcipywrap *self);
+void pcipywrap_unlock_global(pcipywrap *self);
 
 /*!
  * \brief Wrap for pcilib_lock
  * \param lock_id lock identificator
  * \warning This function should be called only under Python standart threading lock.
- * Otherwise it will stuck with more than 1 threads. See /xml/test_pywrap/test_prop_mt.py
+ * Otherwise it will stuck with more than 1 threads. See /xml/test/test_prop4.py
  * for example.
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id);
 
-PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id);
-PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id);
 
 #endif /* PCIPYWRAP_H */

+ 5 - 5
pywrap/pcipywrap.i

@@ -4,13 +4,13 @@
 #include "pcipywrap.h"
 %}
 
-extern void __redirect_logs_to_exeption();
+extern void redirect_logs_to_exeption();
 
 typedef struct {
 	%extend {
-		Pcipywrap(const char* fpga_device = "/dev/fpga0", const char* model = NULL);
-		Pcipywrap(PyObject* ctx){return create_Pcipywrap(ctx);}
-		~Pcipywrap();
+		pcipywrap(const char* fpga_device = "/dev/fpga0", const char* model = NULL);
+		pcipywrap(PyObject* ctx){return create_pcipywrap(ctx);}
+		~pcipywrap();
 	
 		PyObject* read_register(const char *regname = NULL, const char *bank = NULL);
 		PyObject* write_register(PyObject* val, const char *regname, const char *bank = NULL);
@@ -30,4 +30,4 @@ typedef struct {
 		PyObject* try_lock(const char *lock_id);
 		PyObject* unlock(const char *lock_id);
 	}
-} Pcipywrap;
+} pcipywrap;

+ 0 - 347
pywrap/templates/base.html

@@ -1,347 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<title>{% block title %}Device {{ device }}{% endblock %}</title>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-	<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
-	<link rel="stylesheet" type="text/css" href="codebase/dhtmlx.css"/>
-   <script type=text/javascript src="{{ url_for('static', filename='jquery-2.2.1.js') }}"></script>
-	<script src="codebase/dhtmlx.js"></script>
-   <script src="pcilib_tree.js"></script>
-	<script>
-      var propsTree
-      
-      function checkError(json)
-      {
-         if(json.error)
-            alert('Error:\n' + json.error)
-      }
-      
-      function createPropertyTree(branch, id)
-      {
-         function getPropertyItemsOnLevel(branch, id)
-         {
-            pathToProperties = "{{ url_for('get_property_list_json') }}"
-            completePath = pathToProperties + '?branch=' + branch
-            
-            $.getJSON(completePath, 
-                      function(json) {
-                         checkError(json)
-                         parsePropertyItems(json, branch, id)
-                         });
-         }
-         
-         function parsePropertyItems(json, branch, id)
-         {
-            function updatePropertyValue(id, path)
-            {
-               pathToGetProperty = "{{ url_for('get_property_json') }}"
-               completePath = pathToGetProperty + '?prop=' + path
-               
-               $.getJSON(completePath, function(json){
-                           checkError(json)
-                           propsTree.updateItem(id, 'value: ' + json.value);
-                        })
-            }
-         
-            function writePropertyValue(id, path)
-            {
-               value = window.prompt("Enter new property value");
-               
-               if(value != null)
-               {
-                  pathToGetProperty = "{{ url_for('set_property_json') }}"
-                  completePath = pathToGetProperty + '?prop=' + path +'&val=' + value
-                  
-                  $.getJSON(completePath, 
-                            function(json) {
-                              checkError(json)
-                              updatePropertyValue(id, path)
-                             })
-               }
-               else
-                  updatePropertyValue(id, path)
-            }
-            
-            function setCurrentValueField(id, path, mode)
-            {
-               var propValId = id + 'CurrVal'
-               var func = 0
-               
-               if(mode)
-                  func = function(){writePropertyValue(propValId, path)}
-               else
-                  func = function(){updatePropertyValue(propValId, path)}
-                  
-               propsTree.insertNewItem(id, propValId,
-                                    'value: ', 
-                                    func);
-               
-               updatePropertyValue(propValId, path)
-            }
-            
-            for(var i = 0; i < json.length; i++)
-            {
-               propsTree.insertNewItem(id, json[i].path, json[i].name, 0);
-               
-               if(json[i].flags.indexOf("childs") != -1)
-               {
-                  getPropertyItemsOnLevel(json[i].path, json[i].path)
-               }
-               else
-               {
-                  if(json[i].mode.indexOf("R") != -1)
-                  {
-                     var mode = (json[i].mode.indexOf("W") != -1)
-                     setCurrentValueField(json[i].path, json[i].path, mode)
-                  }
-               }
-               
-               //show aviable info
-               if(json[i].description)
-                  propsTree.insertNewItem(json[i].path, json[i].path + 'Desc',
-                                       'description:\n' + json[i].description, 0);
-               if(json[i].type)
-                  propsTree.insertNewItem(json[i].path, json[i].path + 'Type',
-                                       'type: ' + json[i].type, 0);
-               if(json[i].unit)
-                  propsTree.insertNewItem(json[i].path, json[i].path + 'Unit',
-                                       'unit: ' + json[i].unit, 0);
-                                       
-               if(json[i].mode)
-               {
-                  var modeId = json[i].path + 'Mode'
-                  propsTree.insertNewItem(json[i].path, modeId,
-                                       'mode', 0);
-                  
-                  for(var j = 0; j < json[i].mode.length; j++)
-                     propsTree.insertNewItem(modeId, modeId + j,
-                                       json[i].mode[j], 0);
-                  propsTree.closeItem(modeId)
-               }
-               
-               if(json[i].path)
-                  propsTree.insertNewItem(json[i].path, json[i].path + 'Path',
-                                       'path: ' + json[i].path, 0);
-                                       
-               propsTree.closeItem(json[i].path);
-            }  
-      }
-         
-         getPropertyItemsOnLevel(branch, id)
-      }
-      
-      var regTree
-      function createRegistersList()
-      {
-         function parseJsonRegisterList(json)
-         {
-            checkError(json)
-            
-            function compareRegistersByBank(a,b) 
-            {
-               if (a.bank < b.bank)
-                  return -1;
-               else if (a.bank > b.bank)
-                  return 1;
-               else 
-                  return 0;
-            }
-            
-            if(json.lenght <= 0)
-               return
-            
-            //sort registers by bank
-            json.sort(compareRegistersByBank)
-            
-            //create bank dirs
-            var curBankName = json[0].bank
-            var created = 0
-            for(var i = 0; i < json.length; i++)
-            {
-               //create new bank tab if it has not created already
-               if(json[i].bank != curBankName)
-               {
-                  curBankName = json[i].bank
-                  created = 0
-               }
-               if(!created)
-               {
-                  regTree.insertNewItem(0, json[i].bank, json[i].bank, 0);
-                  created = 1
-               }
-               
-               //insert register info to bank
-               var itemId = json[i].bank + "_" + json[i].name
-               regTree.insertNewItem(json[i].bank, itemId, json[i].name)
-               
-               function updateRegisterValue(id, bank, name)
-               {
-                  pathToGetProperty = "{{ url_for('read_register_json') }}"
-                  completePath = pathToGetProperty + '?bank=' + bank +
-                                 '&name=' + name
-                  
-                  $.getJSON(completePath, function(json){
-                              checkError(json)
-                              regTree.updateItem(id, 'value: ' + json.value);
-                           })
-               }
-         
-
-               function writeRegisterValue(id, bank, name)
-               {
-                  value = window.prompt("Enter new register value");
-                  
-                  if(value != null)
-                  {
-                     pathToGetProperty = "{{ url_for('write_register_json') }}"
-                     completePath = pathToGetProperty + '?bank=' + bank +
-                                    '&name=' + name + '&val=' + value;
-                     
-                     $.getJSON(completePath, 
-                               function(json) {
-                                 checkError(json)
-                                 updateRegisterValue(id, bank, name)
-                                })
-                  }
-                  else
-                     updateRegisterValue(id, bank, name)
-               }
-
-               function setCurrentValueField(id, bank, name, mode)
-               {
-                  var regValId = id + 'CurrVal'
-                  var func = 0
-                  
-                  if(mode)
-                     func = function(){writeRegisterValue(regValId, bank, name)}
-                  else
-                     func = function(){updateRegisterValue(regValId, bank, name)}
-                     
-                  regTree.insertNewItem(id, regValId,
-                                       'value: ', 
-                                       func);
-                  updateRegisterValue(regValId, bank, name)
-               }
-               
-               if(json[i].mode.indexOf("R") != -1)
-               {
-                  var mode = (json[i].mode.indexOf("W") != -1)
-                  setCurrentValueField(itemId, json[i].bank, json[i].name, mode)
-               }
-               
-               //show aviable info
-               if(json[i].description)
-                  regTree.insertNewItem(itemId, itemId + 'Desc',
-                                        'description:\n' + json[i].description, 0);
-               if(json[i].defvalue)
-                  regTree.insertNewItem(itemId, itemId + 'Defvalue',
-                                       'defvalue: ' + json[i].defvalue, 0);
-               
-               if(json[i].mode)
-               {
-                  var modeId = itemId + 'Mode'
-                  regTree.insertNewItem(itemId, modeId,
-                                       'mode', 0);
-                  
-                  for(var j = 0; j < json[i].mode.length; j++)
-                     regTree.insertNewItem(modeId, modeId + j,
-                                       json[i].mode[j], 0);
-                  regTree.closeItem(modeId)
-               }
-               
-               if(json[i].range)
-               {
-                  var rangeId = itemId + 'Range'
-                  regTree.insertNewItem(itemId, rangeId,
-                                       'range', 0);
-                  regTree.insertNewItem(rangeId, rangeId + 'Min',
-                                       'min: ' + json[i].range.min, 0);
-                  regTree.insertNewItem(rangeId, rangeId + 'Max',
-                                       'max: ' + json[i].range.max, 0);
-                  regTree.closeItem(rangeId)
-               }
-               
-               if(json[i].values)
-               {
-                  var valuesId = itemId + 'Values'
-                  regTree.insertNewItem(itemId, valuesId,
-                                       'values', 0);
-                                       
-                  function addValueInfo(valuesId, value)
-                  {
-                     var valueId = valuesId + value.name
-                     regTree.insertNewItem(valuesId, valueId, value.name, 0);
-                     
-                     if(value.description)
-                        regTree.insertNewItem(valueId, valueId + 'Desc',
-                                              'description: ' + value.description, 0);
-                     if(value.value)
-                        regTree.insertNewItem(valueId, valueId + 'Value',
-                                              'value: ' + value.value, 0);
-                     if(value.min)
-                        regTree.insertNewItem(valueId, valueId + 'Min',
-                                              'min: ' + value.min, 0);
-                     if(value.max)
-                        regTree.insertNewItem(valueId, valueId + 'Max',
-                                              'max: ' + value.max, 0);   
-                  }
-                  
-                  for(var j = 0; j < json[i].values.length; j++)
-                  {
-                     addValueInfo(valuesId, json[i].values[j])
-                  }
-                  regTree.closeItem(valuesId)
-               }
-                                       
-               propsTree.closeItem(json[i].path);
-               
-               regTree.closeItem(itemId);
-            }
-         }
-         
-         //get registers json list
-         getRegistersListPath = "{{ url_for('get_registers_list_json') }}" 
-         $.getJSON(getRegistersListPath, parseJsonRegisterList);
-      }
-      
-		function doOnLoad()
-      {
-			propsTree = new dhtmlXTreeObject("treeboxbox_tree","100%","100%",0);
-			propsTree.setImagePath("codebase/imgs/dhxtree_skyblue/");
-         //generating properties list
-         createPropertyTree('', 0)
-         
-			regTree = new dhtmlXTreeObject("treeboxbox_tree2","100%","100%",0,0,0,0,'SELECT')
-			regTree.setImagePath("codebase/imgs/dhxtree_skyblue/");
-         createRegistersList()
-		}
-	</script>
-</head>
-<body onload="doOnLoad()">
-	{% block info %}
-      <h2>Device {{ device }} model={{ model }} control page </h2>
-   {% endblock %}
-   
-   {% block content %}
-   {% endblock %}
-	<table>
-		<tr>
-         <td>
-            <h3>Properties Tree</h3>
-         </td>
-         <td>
-            <h3>Registers Tree</h3>
-         </td>
-		</tr>
-		<tr>
-         <td valign="top">
-				<div id="treeboxbox_tree" style="background-color:#f5f5f5;border :1px solid Silver; overflow:auto;"></div>
-			</td>
-			<td valign="top">
-				<div id="treeboxbox_tree2" style="background-color:#f5f5f5;border :1px solid Silver; overflow:auto;"></div>
-			</td>
-		</tr>
-	</table>
-</body>
-</html>

+ 0 - 91
pywrap/templates/property_info.html

@@ -1,91 +0,0 @@
-{% extends "base.html" %}
-{% block title %}Property list{% endblock %}
-{% block info %}
-<h1>List of properties in branch {{ branch }}</h1>
-{% endblock %}
-
-{% block content %}
-
-   <script>
-      function set_property()
-      {
-         var value = document.getElementById("set_val_box").value;
-         window.location.href = "{{ url_for('set_property') }}?prop={{ branch }}&"+
-                                'val='+value;
-      };
-   </script>
-
-<table border="1" style="width:100%">
-   <tr>
-    <th>Name</th>
-    <th>Description</th> 
-   </tr>
-   {% for property in properties %}
-   <tr>
-      {% if ('childs' in property.flags) or (properties|length != 1) %}
-         <td><a href="{{ url_for('get_property_list', branch = property.path) }}">"{{ property.name }}"</td>
-         {% if 'description' in property %}
-      <script>
-      function set_property()
-      {
-         var value = document.getElementById("set_val_box").value;
-         window.location.href = "{{ url_for('set_property') }}?prop={{ branch }}&"+
-                                'val='+value;
-      };
-   </script>
-         <td>{{ property.description }}</td>
-            {% else %}
-            <td></td>
-            {% endif %}
-         {% else %}
-            <td>{{ property.name }}"</td>
-            <td>
-               <table border="1" style="width:100%">
-                  {% if 'description' in property %}
-                  <tr>
-                     <th> Description </th>
-                     <td> {{ property.description }} </td>
-                  </tr>
-                  {% endif %}
-                  <tr>
-                     <th> Current value </th>
-                     <td> {{ value }} </td>
-                  </tr>
-                  {% if 'W' in property.mode %}
-                     <tr>
-                        <th> Set value</th>
-                        <td> 
-                           <input type="text" name="set_val_box" id="set_val_box" value="" />
-                           <input type="button" value="set" onclick="set_property()">
-                        </td>
-                     </tr>
-                  {% endif %}
-                  <tr>
-                     <th>Mode</th>
-                     <td>
-                        <ul>
-                           {% for m in property.mode %}
-                              <li>{{ m }}</li>
-                           {% endfor %}
-                        </ul>
-                     </td>
-                  </tr>
-                  <tr>
-                     <th>Type</th>
-                     <td> {{ property.type }} </td>
-                  </tr>
-                  <tr>
-                     <th>Unit</th>
-                     <td> {{ property.unit }} </td>
-                  </tr>
-                  <tr>
-                     <th>Path</th>
-                     <td> {{ property.path }} </td>
-                  </tr>
-               </table>
-            </td>
-         {% endif %}
-      </tr>
-      {% endfor %}
-   </table>
-{% endblock %}

+ 0 - 106
pywrap/templates/register_info.html

@@ -1,106 +0,0 @@
-{% extends "base.html" %}
-{% block title %}Register info{% endblock %}
-{% block info %}
-<h1>Register '{{ register.name }}' info</h1>
-{% endblock %}
-
-{% block content %}
-   <script>
-      function write_register()
-      {
-         var value = document.getElementById("set_val_box").value;
-         window.location.href = "{{ url_for('write_register') }}?name={{ register.name }}&"+
-                                'bank={{ register.bank }}&val='+value;
-      };
-   </script>
-
-   <table border="1" style="width:100%">
-      {% if 'description' in register %}
-      <tr>
-         <th> Description </th>
-         <td> {{ register.description }} </td>
-      </tr>
-      {% endif %}
-      <tr>
-         <th> Current value </th>
-         <td> {{ value }} </td>
-      </tr>
-      {% if 'W' in register.mode %}
-         <tr>
-            <th> Set value</th>
-            <td> 
-               <input type="text" name="set_val_box" id="set_val_box" value="" />
-               <input type="button" value="set" onclick="write_register()">
-            </td>
-         </tr>
-      {% endif %}
-      <tr>
-         <th>Bank</th>
-         <td>{{ register.bank }}</td>
-      </tr>
-      <tr>
-         <th>Default value</th>
-         <td>{{ register.defvalue }}</td>
-      </tr>
-      <tr>
-         <th>Mode</th>
-         <td>
-            <ul>
-               {% for m in register.mode %}
-                  <li>{{ m }}</li>
-               {% endfor %}
-            </ul>
-         </td>
-      </tr>
-      {% if 'range' in register %}
-      <tr>
-         <th>
-            Range
-         </th>
-         <td>
-            <table>
-               <tr>
-                  <th> min </th>
-                  <td> {{ register.range.min }} </td>
-               </tr>
-               <tr>
-                  <th> max </th>
-                  <td> {{ register.range.max }} </td>
-               </tr>
-            </table>
-         </td>
-      </tr>
-      {% endif %}
-      {% if 'values' in register %}
-         {% for v in register['values'] %}
-            <tr>
-               {% if 'name' in v %}
-                  <th> {{v.name}} </th>
-               {% endif %}
-               <td>
-                  <table>
-                     {% if 'description' in v %}
-                     <tr>
-                        <th> description </th>
-                        <td> {{ v.description }} </td>
-                     </tr>
-                     {% endif %}
-                     <tr>
-                        <th> min </th>
-                        <td> {{ v.min }} </td>
-                     </tr>
-                     <tr>
-                        <th> max </th>
-                        <td> {{ v.max }} </td>
-                     </tr>
-                     <tr>
-                        <th> value </th>
-                        <td> {{ v.value }} </td>
-                     </tr>
-                  </table>
-               </td>
-            </tr>
-         {% endfor %}
-      {% endif %}
-   </table>
-{% endblock %}

+ 0 - 26
pywrap/templates/registers_list.html

@@ -1,26 +0,0 @@
-{% extends "base.html" %}
-{% block title %}Registers list{% endblock %}
-{% block info %}
-<h1>List of aviable registers</h1>
-{% endblock %}
-
-{% block content %}
-<table border="1" style="width:100%">
-   <tr>
-    <th>Name</th>
-    <th>Description</th> 
-  </tr>
-{% for register in registers %}
-   <tr>
-      <td><a href="{{ url_for('get_register_info', bank=register.bank, name=register.name) }}">{{ register.name }}</td>
-      {% if 'description' in register %}
-         <td>{{ register.description }}</td>
-      {% else %}
-         <td></td>
-      {% endif %}
-   </tr>
-{% endfor %}
-</table>
-{% endblock %}
-
-

+ 31 - 26
pywrap/test_pcipywrap.py → pywrap/test_pcilib.py

@@ -1,5 +1,5 @@
 import threading
-import pcipywrap
+import pcilib
 import random
 import os
 import json
@@ -7,7 +7,7 @@ import requests
 import time
 from optparse import OptionParser, OptionGroup
 
-class test_pcipywrap():
+class test_pcilib():
    def __init__(self, 
                 device, 
                 model, 
@@ -35,7 +35,7 @@ class test_pcipywrap():
       #create pcilib_instance
       self.device = device
       self.model = model
-      self.pcilib = pcipywrap.Pcipywrap(device, model)
+      self.pcilib = pcilib.pcilib(device, model)
       self.num_threads = num_threads
       self.write_percentage = write_percentage
       self.register = register
@@ -55,17 +55,17 @@ class test_pcipywrap():
                 {'command': 'unlock_global'},
                 {'command': 'help'}]  
       r = requests.get(url, data=json.dumps(payload[message]), headers=headers)
-      print json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': '))
+      print(json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': ')))
     
    def testThreadSafeReadWrite(self):
       def threadFunc():
          if random.randint(0, 100) >= (self.write_percentage * 100):
             ret = self.pcilib.get_property(self.prop)
-            print self.register, ':', ret
+            print(self.register, ':', ret)
             del ret
          else:
             val = random.randint(0, 65536)
-            print 'set value:', val
+            print('set value:', val)
             self.pcilib.set_property(val, self.prop)
       try:
          while(1):
@@ -74,25 +74,25 @@ class test_pcipywrap():
                thread_list[i].start()
             for i in range(0, self.num_threads):
                thread_list[i].join()
-            print 'cycle done'
+            print('cycle done')
       except KeyboardInterrupt:
-         print 'testing done'
+         print('testing done')
          pass
    
    def testMemoryLeak(self):
       try:
          while(1):
-            val = random.randint(0, 8096)
-            self.pcilib = pcipywrap.Pcipywrap(self.device, self.model)
-            print self.pcilib.get_property_list(self.branch)
-            print self.pcilib.get_register_info(self.register)
-            print self.pcilib.get_registers_list();
-            print self.pcilib.read_register(self.register)
-            print self.pcilib.write_register(val, self.register)
-            print self.pcilib.get_property(self.prop)
-            print self.pcilib.set_property(val, self.prop)
+            val = long(random.randint(0, 8096))
+            self.pcilib = pcilib.pcilib(self.device, self.model)
+            print(self.pcilib.get_property_list(self.branch))
+            print(self.pcilib.get_register_info(self.register))
+            print(self.pcilib.get_registers_list())
+            print(self.pcilib.write_register(val, self.register))
+            print(self.pcilib.read_register(self.register))
+            print(self.pcilib.set_property(val, self.prop))
+            print(self.pcilib.get_property(self.prop))
       except KeyboardInterrupt:
-         print 'testing done'
+         print('testing done')
          pass
 
    def testServer(self):
@@ -111,14 +111,19 @@ class test_pcipywrap():
       
       def sendRandomMessage():
          message_number = random.randint(1, len(payload) - 1)
-         print 'message number: ', message_number
+         print('message number: ', message_number)
          payload[message_number]['value'] =  random.randint(0, 8096)
          r = requests.get(url, data=json.dumps(payload[message_number]), headers=headers)
-         print json.dumps(r.json(), sort_keys=True, indent=4, separators=(',', ': '))
-      
+         if(r.headers['content-type'] == 'application/json'):
+            print(json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': ')))
+         else:
+            print(r.content)      
       try:    
          r = requests.get(url, data=json.dumps(payload[1]), headers=headers)
-         print json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': '))
+         if(r.headers['content-type'] == 'application/json'):
+            print(json.dumps(r.json(), sort_keys=True, indent=3, separators=(',', ': ')))
+         else:
+            print(r.content)
    
          while(1):
             time.sleep(self.server_message_delay)
@@ -127,10 +132,10 @@ class test_pcipywrap():
                thread_list[i].start()
             for i in range(0, self.num_threads):
                thread_list[i].join()
-            print 'cycle done'
+            print('cycle done')
             
       except KeyboardInterrupt:
-         print 'testing done'
+         print('testing done')
          pass
 
 if __name__ == '__main__':
@@ -140,7 +145,7 @@ if __name__ == '__main__':
                      type="string", dest="device", default=str('/dev/fpga0'),
                      help="FPGA device (/dev/fpga0)")                     
    parser.add_option("-m", "--model",  action="store",
-                     type="string", dest="model", default=None,
+                     type="string", dest="model", default=str('test'),
                      help="Memory model (autodetected)")
    parser.add_option("-t", "--threads",  action="store",
                      type="int", dest="threads", default=150,
@@ -232,7 +237,7 @@ if __name__ == '__main__':
    opts = parser.parse_args()[0]
 
    #create pcilib test instance
-   lib = test_pcipywrap(opts.device,
+   lib = test_pcilib(opts.device,
                         opts.model,
                         num_threads = opts.threads,
                         write_percentage = opts.write_percentage,

+ 1 - 1
run

@@ -2,4 +2,4 @@
 
 APP_PATH=`dirname $0`
 
-PYTHONPATH="$APP_PATH/pywrap:$PYTHONPATH" PCILIB_MODEL_DIR="$APP_PATH/xml" LD_LIBRARY_PATH="$APP_PATH/pcilib" $*
+PYTHONPATH="$APP_PATH/pywrap:$PYTHONPATH" PCILIB_SCRIPTS_DIR="$APP_PATH/pyserver/scripts" PCILIB_MODEL_DIR="$APP_PATH/xml" LD_LIBRARY_PATH="$APP_PATH/pcilib" $*

+ 0 - 50
xml/test/cmosis.xml

@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <bank bar="0" size="128" protocol="software_registers" read_address="0x9010" write_address="0x9000" word_size="8" endianess="little" format="%lu" name="cmosis" description="CMOSIS CMV2000 Registers">
-    <register address="1" offset="0" size="16" default="1088" rwmask="0" mode="RW" name="cmosis_number_lines" description="test"/>
-    <register address="3" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start1"/>
-    <register address="5" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start2"/>
-    <register address="7" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start3"/>
-    <register address="9" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start4"/>
-    <register address="11" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start5"/>
-    <register address="13" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start6"/>
-    <register address="15" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start7"/>
-    <register address="17" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_start8"/>
-    <register address="19" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines1"/>
-    <register address="21" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines2"/>
-    <register address="23" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines3"/>
-    <register address="25" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines4"/>
-    <register address="27" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines5"/>
-    <register address="29" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines6"/>
-    <register address="31" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines7"/>
-    <register address="33" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_number_lines8"/>
-    <register address="35" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_sub_s"/>
-    <register address="37" offset="0" size="16" default="0" rwmask="0" mode="RW" name="cmosis_sub_a"/>
-    <register address="39" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_color"/>
-    <register address="40" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_image_flipping"/>
-    <register address="41" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_exp_flags"/>
-    <register address="42" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_time"><view view="formuu3"/><view view="enumm3"/></register>
-    <register address="45" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_step"/>
-    <register address="48" offset="0" size="24" default="1" rwmask="0" mode="RW" name="cmosis_exp_kp1"/>
-    <register address="51" offset="0" size="24" default="1" rwmask="0" mode="RW" name="cmosis_exp_kp2"/>
-    <register address="54" offset="0" size="2" default="1" rwmask="0" mode="RW" name="cmosis_nr_slopes"/>
-    <register address="55" offset="0" size="8" default="1" rwmask="0" mode="RW" name="cmosis_exp_seq"/>
-    <register address="56" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_time2"/>
-    <register address="59" offset="0" size="24" default="1088" rwmask="0" mode="RW" name="cmosis_exp_step2"/>
-    <register address="68" offset="0" size="2" default="1" rwmask="0" mode="RW" name="cmosis_nr_slopes2"/>
-    <register address="69" offset="0" size="8" default="1" rwmask="0" mode="RW" name="cmosis_exp_seq2"/>
-    <register address="70" offset="0" size="16" default="1" rwmask="0" mode="RW" name="cmosis_number_frames"/>
-    <register address="72" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_output_mode"/>
-    <register address="78" offset="0" size="12" default="85" rwmask="0" mode="RW" name="cmosis_training_pattern"/>
-    <register address="80" offset="0" size="18" default="0x3FFFF" rwmask="0" mode="RW" name="cmosis_channel_en"/>
-    <register address="82" offset="0" size="3" default="7" rwmask="0" mode="RW" name="cmosis_special_82"/>
-    <register address="89" offset="0" size="8" default="96" rwmask="0" mode="RW" name="cmosis_vlow2"/>
-    <register address="90" offset="0" size="8" default="96" rwmask="0" mode="RW" name="cmosis_vlow3"/>
-    <register address="100" offset="0" size="14" default="16260" rwmask="0" mode="RW" name="cmosis_offset"/>
-    <register address="102" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_pga"/>
-    <register address="103" offset="0" size="8" default="32" rwmask="0" mode="RW" name="cmosis_adc_gain"/>
-    <register address="111" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_bit_mode"/>
-    <register address="112" offset="0" size="2" default="0" rwmask="0" mode="RW" name="cmosis_adc_resolution"/>
-    <register address="115" offset="0" size="1" default="1" rwmask="0" mode="RW" name="cmosis_special_115"/>
-  </bank>
-</model>

+ 1 - 0
xml/test/props.xml

@@ -3,4 +3,5 @@
   <transform path="/test/prop1" register="test_prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/sensor_temperature:C} - 27315./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
   <transform path="/test/prop2" register="test_prop2" unit="C" script="test_prop2.py" description="test python script #1" write_verification="0" />
   <transform path="/test/prop3" register="test_prop3" unit="C" script="test_prop3.py" description="test python script #2" />
+  <transform path="/test/prop4" register="test_prop4" unit="C" script="test_prop4.py" description="Example of thread safe python property"/>
 </model>

+ 1 - 2
xml/test/test_prop2.py

@@ -1,6 +1,5 @@
 def read_from_register(ctx, value):
    return ctx.get_property('/test/prop3') / 2
-    
+
 def write_to_register(ctx, value):
     ctx.set_property(value*2, '/test/prop3')
-

+ 24 - 0
xml/test/test_prop4.py

@@ -0,0 +1,24 @@
+import time
+import threading
+lock = threading.Lock()
+
+def read_from_register(ctx, value):
+   with lock:
+      ctx.lock('test_prop4')
+
+      cur = read_from_register.counter
+      read_from_register.counter += 1
+      for i in range (0, 5):
+         time.sleep(0.1)
+         print(cur)
+      out = ctx.get_property('/test/prop3') / 2
+
+      ctx.unlock('test_prop4')
+
+      return out
+
+read_from_register.counter = 0
+
+def write_to_register(ctx, value):
+   with lock:
+      ctx.set_property(value*2, '/test/prop3')