py_ext/PythonFileCTNMixin.py
changeset 2697 93333d206198
parent 2694 3225990eb33e
child 3096 fc5a0b1ece10
equal deleted inserted replaced
2696:9bd639e9124e 2697:93333d206198
   167     "%(IECtype)s",
   167     "%(IECtype)s",
   168     %(initial)s,
   168     %(initial)s,
   169     %(desc)s,
   169     %(desc)s,
   170     %(onchange)s,
   170     %(onchange)s,
   171     %(opts)s))
   171     %(opts)s))
   172 """ % varinfo for varinfo in varinfos])
   172 """ % varinfo + ("""
       
   173 _PyOnChangeCount_%(name)s = ctypes.c_uint.in_dll(PLCBinary,"__%(name)s_onchange_count")
       
   174 _PyOnChangeFirst_%(name)s = _%(name)s_ctype.in_dll(PLCBinary,"__%(name)s_onchange_firstval")
       
   175 _PyOnChangeLast_%(name)s = _%(name)s_ctype.in_dll(PLCBinary,"__%(name)s_onchange_lastval")
       
   176 """ % varinfo if varinfo["onchange"] else "") for varinfo in varinfos])
   173 
   177 
   174         on_change_func_body = "\n".join(["""
   178         on_change_func_body = "\n".join(["""
   175     if changes.next():
   179     if _PyOnChangeCount_%(name)s.value > 0:
   176         # %(name)s
   180         # %(name)s
   177         try:""" % varinfo + """
   181         try:""" % varinfo + """
   178             """ + """
   182             """ + """
   179             """.join(varinfo['onchangecode'])+"""
   183             """.join(varinfo['onchangecode'])+"""
   180         except Exception as e:
   184         except Exception as e:
   213 ## Code for PLC global variable access
   217 ## Code for PLC global variable access
   214 from runtime.typemapping import TypeTranslator
   218 from runtime.typemapping import TypeTranslator
   215 import ctypes
   219 import ctypes
   216 
   220 
   217 _PySafeGetChanges_%(pyextname)s = PLCBinary.PySafeGetChanges_%(location_str)s
   221 _PySafeGetChanges_%(pyextname)s = PLCBinary.PySafeGetChanges_%(location_str)s
   218 _PySafeGetChanges_%(pyextname)s.restype = ctypes.POINTER(ctypes.c_int * %(onchange_var_count)d)
   222 _PySafeGetChanges_%(pyextname)s.restype = None
   219 _PySafeGetChanges_%(pyextname)s.argtypes = None
   223 _PySafeGetChanges_%(pyextname)s.argtypes = None
   220 
   224 
   221 _%(pyextname)sGlobalsDesc = []
   225 _%(pyextname)sGlobalsDesc = []
   222 __ext_name__ = "%(pyextname)s"
   226 __ext_name__ = "%(pyextname)s"
   223 PLCGlobalsDesc.append(( "%(pyextname)s" , _%(pyextname)sGlobalsDesc ))
   227 PLCGlobalsDesc.append(( "%(pyextname)s" , _%(pyextname)sGlobalsDesc ))
   228 
   232 
   229 ## Beremiz python runtime calls
   233 ## Beremiz python runtime calls
   230 %(rtcalls)s
   234 %(rtcalls)s
   231 
   235 
   232 def On_%(pyextname)s_Change():
   236 def On_%(pyextname)s_Change():
   233     changesP = _PySafeGetChanges_%(pyextname)s()
   237     _PySafeGetChanges_%(pyextname)s()
   234     if not changesP:
       
   235         raise Exception("PySafeGetChanges returned NULL!")
       
   236     changes = iter(changesP.contents)
       
   237     errors = []
   238     errors = []
   238 %(on_change_func_body)s
   239 %(on_change_func_body)s
   239     if len(errors)>0 :
   240     if len(errors)>0 :
   240         raise Exception("Exception in %(pyextname)s OnChange call:\\\\n" + "\\\\n".join(errors))
   241         raise Exception("Exception in %(pyextname)s OnChange call:\\\\n" + "\\\\n".join(errors))
   241 
   242 
   272 }
   273 }
   273 
   274 
   274 """
   275 """
   275 
   276 
   276         vardeconchangefmt = """\
   277         vardeconchangefmt = """\
   277 int __%(name)s_rbuffer_written = 0;
   278 unsigned int __%(name)s_rbuffer_written = 0;
       
   279 IEC_%(IECtype)s __%(name)s_rbuffer_firstval;
       
   280 IEC_%(IECtype)s __%(name)s_rbuffer_lastval;
       
   281 unsigned int __%(name)s_onchange_count = 0;
       
   282 IEC_%(IECtype)s __%(name)s_onchange_firstval;
       
   283 IEC_%(IECtype)s __%(name)s_onchange_lastval;
   278 """
   284 """
   279 
   285 
   280         varretfmt = """\
   286         varretfmt = """\
   281     if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
   287     if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
   282         if(__%(name)s_wbuffer_written == 1){
   288         if(__%(name)s_wbuffer_written == 1){
   295 
   301 
   296         varpubonchangefmt = """\
   302         varpubonchangefmt = """\
   297     if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
   303     if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
   298         IEC_%(IECtype)s tmp = __GET_VAR(%(configname)s__%(uppername)s);
   304         IEC_%(IECtype)s tmp = __GET_VAR(%(configname)s__%(uppername)s);
   299         if(NE_%(IECtype)s(1, NULL, __%(name)s_rbuffer, tmp)){
   305         if(NE_%(IECtype)s(1, NULL, __%(name)s_rbuffer, tmp)){
       
   306             if(__%(name)s_rbuffer_written == 0);
       
   307                 __%(name)s_rbuffer_firstval = __%(name)s_rbuffer;
       
   308             __%(name)s_rbuffer_lastval = tmp;
   300             __%(name)s_rbuffer = tmp;
   309             __%(name)s_rbuffer = tmp;
   301             /* mark variable as changed */
   310             /* count one more change */
   302             __%(name)s_rbuffer_written = 1;
   311             __%(name)s_rbuffer_written += 1;
   303             some_change = 1;
   312             some_change_found = 1;
   304         }
   313         }
   305         AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
   314         AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
   306     }
   315     }
   307 """
   316 """
   308 
   317 
   309         varcollectchangefmt = """\
   318         varcollectchangefmt = """\
   310     while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1));
   319     while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1));
   311     pysafe_changes[change_index++] = __%(name)s_rbuffer_written;
   320     __%(name)s_onchange_count = __%(name)s_rbuffer_written;
       
   321     __%(name)s_onchange_firstval = __%(name)s_rbuffer_firstval;
       
   322     __%(name)s_onchange_lastval = __%(name)s_rbuffer_lastval;
   312     /* mark variable as unchanged */
   323     /* mark variable as unchanged */
   313     __%(name)s_rbuffer_written = 0;
   324     __%(name)s_rbuffer_written = 0;
   314     AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
   325     AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
   315 
   326 
   316 """
   327 """
   317         vardec = "\n".join([(vardecfmt + vardeconchangefmt
   328         vardec = "\n".join([(vardecfmt + vardeconchangefmt
   318                              if varinfo["onchange"] else vardecfmt) % varinfo
   329                              if varinfo["onchange"] else vardecfmt) % varinfo
   319                             for varinfo in varinfos])
   330                             for varinfo in varinfos])
   369 
   380 
   370 void __retrieve_%(location_str)s(void){
   381 void __retrieve_%(location_str)s(void){
   371 %(varret)s
   382 %(varret)s
   372 }
   383 }
   373 
   384 
       
   385 static int passing_changes_to_python = 0;
   374 void __publish_%(location_str)s(void){
   386 void __publish_%(location_str)s(void){
   375     int some_change = 0;
   387     int some_change_found = 0;
   376 %(varpub)s
   388 %(varpub)s
       
   389     passing_changes_to_python |= some_change_found;
   377     // call python part if there was at least a change
   390     // call python part if there was at least a change
   378     if(some_change){
   391     if(passing_changes_to_python){
   379         PYTHON_POLL_body__(__%(location_str)s_notifier);
   392         PYTHON_POLL_body__(__%(location_str)s_notifier);
       
   393         passing_changes_to_python &= !(__GET_VAR(__%(location_str)s_notifier->ACK,));
   380     }
   394     }
   381 }
   395 }
   382 
   396 
   383 static int pysafe_changes[%(onchange_var_count)d];
       
   384 void* PySafeGetChanges_%(location_str)s(void){
   397 void* PySafeGetChanges_%(location_str)s(void){
   385     int change_index=0;
       
   386 %(varcollectchange)s
   398 %(varcollectchange)s
   387     return (void*)&pysafe_changes[0];
       
   388 }
   399 }
   389 
   400 
   390 """ % loc_dict
   401 """ % loc_dict
   391 
   402 
   392         Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c" % location_str)
   403         Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c" % location_str)