QuakeGod
2023-10-08 483170e190a0dd4666b2a63e5d31466052ba0c6a
提交 | 用户 | age
483170 1 /**
Q 2   ******************************************************************************
3   * @file           : PLCfunctions.c
4   * @brief          : PLC funcstions program body
5   ******************************************************************************
6     */
7 //#include "globaldef.h"
8 #include "PLCfunctions.h"
9 #include "string.h"
10 #include "stm32f0xx_hal.h"
11 #include <core_cmInstr.h>
12
13 extern __IO uint32_t uwTick;
14
15 //unsigned short WDFs[TOTAL_WDFS];
16
17 inline unsigned int GetTick(void)
18 {
19 //    unsigned short Clk1=SysTick->VAL;
20         return uwTick;
21 }
22
23 //unsigned char CurVAL;
24 //unsigned char CurVALs[TOTAL_CurVAL];
25 //stTimer Timers[TOTALTIMERS];
26
27 //unsigned short WX[13];
28 //unsigned short WY[13];
29 //unsigned short WR[64];
30 //unsigned short DT[256];
31
32 //unsigned short SDT[256];
33
34 stPLCMem PLCMem;
35
36 int InitTimer(int nIndex, int nType)
37 {
38     if (nIndex >= TOTALTIMERS) return -1;
39     KMem.Timers[nIndex].StatByte = 0x0010 | nType;
40 //    Timers[nIndex].nType = 0;
41     KMem.SV[nIndex] = 0;
42     KMem.EV[nIndex] = 0;
43     KMem.Timers[nIndex].LastActTime = GetTick();
44     return 0;
45 }
46
47 int RunTimer(int nIndex , int SV)
48 {
49     if (nIndex >= TOTALTIMERS) return -1;    
50     if (!KMem.Timers[nIndex].bSet)
51     {
52         KMem.SV[nIndex] = SV;
53         KMem.EV[nIndex]= 0;
54         KMem.Timers[nIndex].LastActTime = GetTick();        
55         KMem.Timers[nIndex].bSet = 1;
56     }
57     return 0;
58 }
59
60 int StopTimer(int nIndex)
61 {
62     if (nIndex >= TOTALTIMERS) return -1;    
63     if (KMem.Timers[nIndex].bSet)
64     {
65         KMem.EV[nIndex] = 0;
66         KMem.Timers[nIndex].LastActTime = GetTick();        
67         KMem.Timers[nIndex].bSet = 0;        
68     }
69     return 0;
70 }
71 int ResetTimer(int nIndex)
72 {
73     if (nIndex >= TOTALTIMERS) return -1;
74     KMem.EV[nIndex] = 0;
75     KMem.Timers[nIndex].bTon = 0;
76     KMem.Timers[nIndex].LastActTime=GetTick();
77     return 0;
78 }
79
80 int SetTimerValue(int nIndex, int bSet, int SV)
81 {
82     if (nIndex >= TOTALTIMERS) return -1;    
83     if (bSet) {RunTimer(nIndex, SV);}
84     else {StopTimer(nIndex);}
85     return KMem.Timers[nIndex].bTon;
86 }
87
88 int ProcessTimer(int nIndex)
89 {
90     if (nIndex >= TOTALTIMERS) return -1;
91     if (!KMem.Timers[nIndex].nInited) return 0;
92     if (KMem.Timers[nIndex].bSet)        // bSet =1;
93     {
94         if (!KMem.Timers[nIndex].bTon)
95         {
96             int TimeDiff = GetTick() - KMem.Timers[nIndex].LastActTime;
97             int nScale = TICK_OF_MS;
98             if (KMem.Timers[nIndex].nScale == 0)
99             {nScale = TICK_OF_MS;
100             }else if (KMem.Timers[nIndex].nScale == 1)
101             {nScale = TICK_OF_RS;
102             }else if (KMem.Timers[nIndex].nScale == 2)
103             {nScale = TICK_OF_XS;
104             }else if (KMem.Timers[nIndex].nScale == 3)
105             {nScale = TICK_OF_YS;
106             }else {}
107             
108             
109             if (TimeDiff >= nScale)
110             {
111                 int TimeDiffmS = TimeDiff / nScale;
112                 unsigned short NextEV = KMem.EV[nIndex] + TimeDiffmS;
113                 KMem.Timers[nIndex].LastActTime += TimeDiffmS*nScale;
114                 
115                 if (NextEV >= KMem.SV[nIndex]) 
116                 {
117                     NextEV = KMem.SV[nIndex];
118                     KMem.Timers[nIndex].bTon =1;
119                 }
120                 KMem.EV[nIndex] = NextEV;
121             }
122         }
123     }else         //bSet=0;
124     {
125         if(KMem.Timers[nIndex].bTon) 
126         {
127             KMem.Timers[nIndex].bTon =    0;
128         }
129     }
130     SetCoilValue(KLCoilTypeT, nIndex, KMem.Timers[nIndex].bTon);    
131     return KMem.Timers[nIndex].bTon;
132 }
133
134 int IsTimerOn(int nIndex)
135 {
136     if (nIndex >= TOTALTIMERS) return 0;
137     ProcessTimer(nIndex);
138     return KMem.Timers[nIndex].bTon;
139
140 }
141
142 int GetTimerSV(int nIndex)
143 {
144     if (nIndex >= TOTALTIMERS) return 0;
145 //    ProcessTimer(nIndex);    
146     return KMem.SV[nIndex];
147 //    return 0;    
148 }
149 int GetTimerEV(int nIndex)
150 {
151     if (nIndex >= TOTALTIMERS) return 0;
152 //    ProcessTimer(nIndex);    
153     return KMem.EV[nIndex];
154 //    return 0;
155 }
156
157 int PushInVal(void)
158 {
159     for (int i=TOTAL_CurVAL -1 ;i>0;i--)
160     {
161         KMem.CurVALs[i]=KMem.CurVALs[i-1];
162     }
163     KMem.CurVALs[0]=KMem.CurVAL;
164     return KMem.CurVAL;
165 }
166
167 int PopOutVal(void)
168 {
169     unsigned char theVAL=KMem.CurVALs[0];
170     for (int i=0;i<TOTAL_CurVAL-1;i++)
171     {
172         KMem.CurVALs[i]=KMem.CurVALs[i+1];
173     }
174     return theVAL;
175 }
176
177 stBinProg1 const  prog1[]= //__attribute__((at(0X8008000)))
178 {
179     {OP_ST,KLCoilTypeSR,13},
180     {OP_MV,0,50},    {KLDataTypeDEC,KLDataTypeDT,1},
181     {OP_MV,0,20},    {KLDataTypeDEC,KLDataTypeDT,2},
182     {OP_MV,0,30},    {KLDataTypeDEC,KLDataTypeDT,3},
183     {OP_MV,0,40},    {KLDataTypeDEC,KLDataTypeDT,4},
184     {OP_SET,KLCoilTypeR,0},
185 //    {OP_SET,KLCoilTypeY,0},
186     
187     {OP_ST,KLCoilTypeR,0},
188         {OP_TMX,1,1},    {KLDataTypeDT,0,0},
189         {OP_DF},
190         {OP_SET,KLCoilTypeR,10},
191         
192     {OP_ST,KLCoilTypeX,0},
193     {OP_DF},
194     {OP_SET,KLCoilTypeR,10},
195
196     {OP_ST,KLCoilTypeX,1},
197     {OP_DF},
198     {OP_RESET,KLCoilTypeR,10},
199 /*    
200     {OP_ST,KLCoilTypeR,10},
201     {OP_AN,KLCoilTypeR,51},    
202     {OP_AN,KLCoilTypeR,52},    
203     {OP_AN,KLCoilTypeR,53},    
204     {OP_ADD3,0,21},        {KLDataTypeDT,KLDataTypeDT,31},        {0,KLDataTypeDT,32},    
205
206     {OP_ST,KLCoilTypeR,10},
207     {OP_AN,KLCoilTypeR,54},    
208     {OP_AN,KLCoilTypeR,55},    
209     {OP_AN,KLCoilTypeR,56},    
210     {OP_ADD3,0,23},        {KLDataTypeDT,KLDataTypeDT,33},        {0,KLDataTypeDT,34},    
211 */
212     {OP_ST,KLCoilTypeSR,1},
213     {OP_PSHS},    
214     {OP_AN,KLCoilTypeR,51},    
215     {OP_OUT,KLCoilTypeY,1},    
216     {OP_RDS},    
217     {OP_AN,KLCoilTypeR,52},    
218     {OP_OUT,KLCoilTypeY,2},    
219     {OP_RDS},    
220     {OP_AN,KLCoilTypeR,53},    
221     {OP_OUT,KLCoilTypeY,3},    
222     {OP_RDS},    
223     {OP_AN,KLCoilTypeR,54},    
224     {OP_OUT,KLCoilTypeY,4},    
225     {OP_RDS},    
226     {OP_AN,KLCoilTypeR,55},    
227     {OP_OUT,KLCoilTypeY,5},    
228     {OP_POPS},    
229     {OP_AN,KLCoilTypeR,56},    
230     {OP_OUT,KLCoilTypeY,6},    
231
232     {OP_ST,KLCoilTypeR,10},
233     {OP_DF},
234     {OP_PSHS},    
235     {OP_MV,0,150},    {KLDataTypeDEC,KLDataTypeDT,11},
236     {OP_MV,0,30},    {KLDataTypeDEC,KLDataTypeDT,12},
237     {OP_RDS},    
238     {OP_MV,0,150},    {KLDataTypeDEC,KLDataTypeDT,13},
239     {OP_MV,0,30},    {KLDataTypeDEC,KLDataTypeDT,14},
240     {OP_POPS},    
241     {OP_AN_,KLCoilTypeR,11},    
242     {OP_AN_,KLCoilTypeR,12},    
243     {OP_AN_,KLCoilTypeR,13},    
244     {OP_AN_,KLCoilTypeR,14},    
245     {OP_SET,KLCoilTypeR,14},
246
247     {OP_ST,KLCoilTypeR,10},
248     {OP_PSHS},    
249     {OP_AN,KLCoilTypeR,11},    
250     {OP_DF},
251     {OP_SET,KLCoilTypeR,51},
252     {OP_RESET,KLCoilTypeR,52},
253     {OP_RESET,KLCoilTypeR,53},
254     {OP_RESET,KLCoilTypeR,54},
255     {OP_RESET,KLCoilTypeR,55},
256     {OP_SET,KLCoilTypeR,56},
257
258     {OP_RDS},    
259     {OP_AN,KLCoilTypeR,11},    
260
261         {OP_PSHS},    
262         {OP_TMX,11,11},    {KLDataTypeDT,0,0},
263             {OP_RESET,KLCoilTypeR,11},
264             {OP_SET,KLCoilTypeR,12},
265         {OP_POPS},
266             {OP_SUB3,0,11},        {KLDataTypeSV,KLDataTypeEV,11},        {0,KLDataTypeDT,21},        
267             {OP_AN_LE,0,21},{KLDataTypeDT,KLDataTypeDEC,30},
268             {OP_PSHS},    
269                 {OP_DIV,0,21},        {KLDataTypeDT,KLDataTypeDEC,10},        {0,KLDataTypeDT,31},        
270             {OP_RDS},    
271                 {OP_AN_GE,0,32},{KLDataTypeDT,KLDataTypeDEC,5},
272                 {OP_SET,KLCoilTypeR,51},
273             {OP_POPS},
274                 {OP_AN_LT,0,32},{KLDataTypeDT,KLDataTypeDEC,5},
275                 {OP_RESET,KLCoilTypeR,51},
276     {OP_RDS},            
277     {OP_AN,KLCoilTypeR,12},    
278     {OP_DF},
279     {OP_RESET,KLCoilTypeR,51},
280     {OP_SET,KLCoilTypeR,52},
281     {OP_RDS},            
282     {OP_AN,KLCoilTypeR,12},    
283         {OP_TMX,12,12},    {KLDataTypeDT,0,0},
284             {OP_RESET,KLCoilTypeR,12},
285             {OP_SET,KLCoilTypeR,13},
286     {OP_POPS},
287     {OP_AN,KLCoilTypeR,12},    
288     {OP_OUT,KLCoilTypeR,52},    
289     
290     {OP_ST,KLCoilTypeR,10},
291     {OP_PSHS},    
292     {OP_AN,KLCoilTypeR,13},    
293     {OP_DF},
294     {OP_RESET,KLCoilTypeR,52},
295     {OP_SET,KLCoilTypeR,53},
296     {OP_SET,KLCoilTypeR,54},
297     {OP_RESET,KLCoilTypeR,56},
298     {OP_RDS},    
299     {OP_AN,KLCoilTypeR,13},    
300         {OP_TMX,13,13},    {KLDataTypeDT,0,0},
301             {OP_RESET,KLCoilTypeR,13},
302             {OP_SET,KLCoilTypeR,14},
303     {OP_RDS},    
304     {OP_AN,KLCoilTypeR,13},    
305             {OP_SUB3,0,13},        {KLDataTypeSV,KLDataTypeEV,13},        {0,KLDataTypeDT,23},        
306             {OP_AN_LE,0,23},{KLDataTypeDT,KLDataTypeDEC,30},
307             {OP_PSHS},    
308                 {OP_DIV,0,23},        {KLDataTypeDT,KLDataTypeDEC,10},        {0,KLDataTypeDT,33},        
309             {OP_RDS},    
310                 {OP_AN_GE,0,34},{KLDataTypeDT,KLDataTypeDEC,5},
311                 {OP_SET,KLCoilTypeR,54},
312             {OP_POPS},
313                 {OP_AN_LT,0,34},{KLDataTypeDT,KLDataTypeDEC,5},
314                 {OP_RESET,KLCoilTypeR,54},
315     {OP_RDS},    
316     {OP_AN,KLCoilTypeR,14},    
317     {OP_DF},
318     {OP_RESET,KLCoilTypeR,54},
319     {OP_SET,KLCoilTypeR,55},
320     {OP_POPS},
321     {OP_AN,KLCoilTypeR,14},    
322         {OP_TMX,14,14},    {KLDataTypeDT,0,0},
323             {OP_RESET,KLCoilTypeR,14},
324             {OP_SET,KLCoilTypeR,11},
325 };
326
327 /*
328
329     {OP_ST,Addr_R,1},
330     {OP_PSHS,0,0},
331     {OP_AN_,Addr_Y,1},
332     {OP_TMR,5,200},
333     {OP_SET,Addr_Y,1},
334     {OP_POPS,0,0},
335     {OP_AN,Addr_Y,1},
336     {OP_TMR,6,200},
337     {OP_RESET,Addr_Y,1},
338
339 */
340 int nSizeProg1=sizeof(prog1)/sizeof(stBinProg1);
341
342 int InitPLC()
343 {
344     PLCMem.nScanCount=0;
345     for (int i=0;i<256;i++){PLCMem.ProgTrace[i]=0;}
346     for (int i=0;i<16;i++)    {
347         KMem.WR[i]=0;
348     }
349     for (int i=0;i<256;i++)    {
350         KMem.DT[i]=0;
351     }
352     return 0;
353 }
354
355 int StartPLC()
356 {
357     PLCMem.nScanCount = 0;
358     for (int i=0;i<256;i++){PLCMem.ProgTrace[i]=0;}
359     for (int i=0;i<16;i++)    {
360         KMem.WR[i]=0;
361     }
362     for (int i=0;i<256;i++)    {
363         KMem.DT[i]=0;
364     }
365     for (int i=0;i<TOTALTIMERS;i++){
366         KMem.Timers[i].nInited=0;
367     }
368     
369     PLCMem.bPLCRunning=1;
370     KMRunStat.WorkMode2=PLCMem.bPLCRunning;
371     return 0;
372 }
373
374 int StopPLC()
375 {
376     PLCMem.bPLCRunning=0;
377     for (int i=0;i<KLDataWXCount;i++) KMem.WY[i]=0;
378     for (int i=0;i<KLDataWLCount;i++) KMem.WLY[i]=0;
379     return 0;
380 }
381
382 inline void SetAddrBit(unsigned short * pW, unsigned char bitAddr)
383 {
384     (*pW)|=1<<(bitAddr&0xf);
385 }
386
387 inline void ResetBit(unsigned short * pW, unsigned char bitAddr)
388 {
389     (*pW)&=~(1<<(bitAddr&0xf));
390 }
391 static inline void SetBitValue(unsigned short * pW, unsigned char bitAddr, unsigned char Value)
392 {
393     if (Value)    {    SetAddrBit(pW, bitAddr);}
394     else {ResetBit(pW, bitAddr);}
395 }
396
397 static inline unsigned char GetBitValue(unsigned short W, unsigned char bitAddr)
398 {
399     if (W&(1<<(bitAddr&0xf))) return 1;
400     else return 0;
401 }
402
403
404 int ProcessPLCBinProg(const stBinProg1 * pBinprog, int nStepSize)
405 {
406     if (!PLCMem.bPLCRunning) return 0;
407     
408     if (PLCMem.nScanCount == 0) {
409         SetCoilValue(KLCoilTypeSR, 13, 1);
410         SetCoilValue(KLCoilTypeSR, 0, 0);
411         SetCoilValue(KLCoilTypeSR, 1, 1);
412     }
413     else
414     {
415         SetCoilValue(KLCoilTypeSR, 13, 0);
416         SetCoilValue(KLCoilTypeSR, 0, 0);
417         SetCoilValue(KLCoilTypeSR, 1, 1);
418     }
419     for (int i = 0; i < TOTAL_CurVAL; i++) {
420         KMem.CurVALs[i] = 0;
421     }
422     int CurPos = 0;
423 //    stBinProg1 * pBinProg1;
424     stBinProg15 * pBinProg15;
425     stBinProg2 * pBinProg2;
426     stBinProg3 * pBinProg3;
427
428     int lastScanInputVal = 1;//??????,????????,? ?? ???
429
430     while (CurPos < nStepSize)
431     {
432         unsigned int nNextPos = 1;
433         unsigned int thisOP = pBinprog[CurPos].nOp;
434 //        unsigned int nParamCount = 0
435         unsigned char thisAddrType = pBinprog[CurPos].nParamType;
436         unsigned short thisAddr = pBinprog[CurPos].nParamAddr;
437
438
439         switch (thisOP)
440         {
441 //        case OP_NONE:
442 //            break;
443         case OP_NOP:
444             break;
445             //??? ??
446         case OP_NOT:
447         case OP_ANS:
448         case OP_ORS:
449         case OP_PSHS:
450         case OP_RDS:
451         case OP_POPS:
452         case OP_DF:
453         case OP_DF_:
454             switch (thisOP)
455             {
456             case OP_NOT:
457                 KMem.CurVAL = !KMem.CurVAL;
458                 break;
459             case OP_ANS:
460                 KMem.CurVAL = PopOutVal() && KMem.CurVAL;
461                 break;
462             case OP_ORS:
463                 KMem.CurVAL = PopOutVal() || KMem.CurVAL;
464                 break;
465             case OP_PSHS:
466                 PushInVal();
467                 break;
468             case OP_RDS:
469                 KMem.CurVAL = KMem.CurVALs[0] != 0;
470                 break;
471             case OP_POPS:
472                 KMem.CurVAL = PopOutVal();
473                 break;
474             case OP_DF:
475                 KMem.CurVAL = KMem.CurVAL && !lastScanInputVal;
476                 break;
477             case OP_DF_:
478                 KMem.CurVAL = !KMem.CurVAL && lastScanInputVal;
479                 break;
480
481             default:
482                 break;
483             }
484             break;
485             // 1????
486         case OP_ST:
487         case OP_ST_:
488         case OP_AN:
489         case OP_AN_:
490         case OP_OR:
491         case OP_OR_:
492             switch (thisOP)
493             {
494             case OP_ST:
495                 PushInVal();
496                 KMem.CurVAL = GetCoilValue(thisAddrType, thisAddr);
497                 break;
498             case OP_ST_:
499                 PushInVal();
500                 KMem.CurVAL = !GetCoilValue(thisAddrType, thisAddr);
501                 break;
502             case OP_AN:
503                 KMem.CurVAL = KMem.CurVAL&&GetCoilValue(thisAddrType, thisAddr);
504                 break;
505             case OP_AN_:
506                 KMem.CurVAL = KMem.CurVAL && (!GetCoilValue(thisAddrType, thisAddr));
507                 break;
508             case OP_OR:
509                 KMem.CurVAL = KMem.CurVAL || GetCoilValue(thisAddrType, thisAddr);
510                 break;
511             case OP_OR_:
512                 KMem.CurVAL = KMem.CurVAL || (!GetCoilValue(thisAddrType, thisAddr));
513                 break;
514             default:
515                 break;
516             }
517             break;
518             // 1 ?? ??
519         case OP_OUT:
520         case OP_SET:
521         case OP_RESET:
522             switch (thisOP)
523             {
524             case OP_OUT:
525                 SetCoilValue(thisAddrType, thisAddr, KMem.CurVAL);
526                 break;
527             case OP_SET:
528                 if (KMem.CurVAL) SetCoilValue(thisAddrType, thisAddr, 1);
529                 break;
530             case OP_RESET:
531                 if (KMem.CurVAL) SetCoilValue(thisAddrType, thisAddr, 0);
532                 break;
533             default:
534                 break;
535             }
536             break;
537             // ????
538         case OP_ST_EQ:
539         case OP_ST_NE:
540         case OP_ST_LT:
541         case OP_ST_GT:
542         case OP_ST_LE:
543         case OP_ST_GE:
544         case OP_AN_EQ:
545         case OP_AN_NE:
546         case OP_AN_LT:
547         case OP_AN_GT:
548         case OP_AN_LE:
549         case OP_AN_GE:
550         case OP_OR_EQ:
551         case OP_OR_NE:
552         case OP_OR_LT:
553         case OP_OR_GT:
554         case OP_OR_LE:
555         case OP_OR_GE:
556             pBinProg2 = (stBinProg2 *)&pBinprog[CurPos];
557             thisAddrType = pBinProg2->nParamType1;
558
559             switch (thisOP)
560             {
561             case OP_ST_EQ:
562                 PushInVal();
563                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
564                 break;
565             case OP_ST_NE:
566                 PushInVal();
567                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
568                 break;
569             case OP_ST_LT:
570                 PushInVal();
571                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
572                 break;
573             case OP_ST_GT:
574                 PushInVal();
575                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
576                 break;
577             case OP_ST_LE:
578                 PushInVal();
579                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
580                 break;
581             case OP_ST_GE:
582                 PushInVal();
583                 KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
584                 break;
585             case OP_AN_EQ:
586                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
587                 break;
588             case OP_AN_NE:
589                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
590                 break;
591             case OP_AN_LT:
592                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
593                 break;
594             case OP_AN_GT:
595                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
596                 break;
597             case OP_AN_LE:
598                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
599                 break;
600             case OP_AN_GE:
601                 KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
602                 break;
603
604             case OP_OR_EQ:
605                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
606                 break;
607             case OP_OR_NE:
608                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
609                 break;
610             case OP_OR_LT:
611                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
612                 break;
613             case OP_OR_GT:
614                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
615                 break;
616             case OP_OR_LE:
617                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
618                 break;
619             case OP_OR_GE:
620                 KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
621                 break;
622
623             default:
624                 break;
625             }
626             nNextPos = 2;
627             break;
628             // ???
629         case OP_TML:
630         case OP_TMR:
631         case OP_TMX:
632         case OP_TMY:
633             pBinProg15 = (stBinProg15 *)(&pBinprog[CurPos]);
634             {
635                 unsigned char thisNum= pBinProg15->nOpNum;
636                 thisAddrType = pBinProg15->nParamType1;
637                 thisAddr = pBinProg15->nParamAddr1;
638                 switch (thisOP)
639                 {
640                 case OP_TML:
641                     if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 0);
642                     if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
643                     else StopTimer(thisNum);
644                     KMem.CurVAL = ProcessTimer(thisNum);
645
646                     break;
647                 case OP_TMR:
648                     if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 1);
649                     if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
650                     else StopTimer(thisNum);
651                     KMem.CurVAL = ProcessTimer(thisNum);
652                     break;
653                 case OP_TMX:
654                     if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 2);
655                     if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
656                     else StopTimer(thisNum);
657                     KMem.CurVAL = ProcessTimer(thisNum);
658
659                     break;
660                 case OP_TMY:
661                     if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 3);
662                     if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
663                     else StopTimer(thisNum);
664                     KMem.CurVAL = ProcessTimer(thisNum);
665                     break;
666                 default:
667                     break;
668                 }
669
670             }
671             nNextPos = 2;
672             break;
673             // 1 ??????
674         case OP_INC:
675         case OP_DEC:
676             pBinProg15 = (stBinProg15 *)(&pBinprog[CurPos]);
677             thisAddrType = pBinProg15->nParamType1;
678             thisAddr = pBinProg15->nParamAddr1;
679             nNextPos = 2;
680             switch (thisOP)
681             {
682             case OP_INC:
683                 if (KMem.CurVAL) SetVarData(thisAddrType, thisAddr, GetVarData(thisAddrType, thisAddr) + 1);
684                 break;
685             case OP_DEC:
686                 if (KMem.CurVAL) SetVarData(thisAddrType, thisAddr, GetVarData(thisAddrType, thisAddr) - 1);
687                 break;
688
689             default:
690                 break;
691             }
692             break;
693             // 2??????
694         case OP_MV:
695         case OP_ADD2:
696         case OP_SUB2:
697             pBinProg2 = (stBinProg2 *)(&pBinprog[CurPos]);
698             {
699                 int nParamType2, nParamAddr2;
700                 thisAddrType = pBinProg2->nParamType1;
701                 thisAddr = pBinProg2->nParamAddr1;
702                 nParamType2 = pBinProg2->nParamType2;
703                 nParamAddr2 = pBinProg2->nParamAddr2;
704
705                 switch (thisOP)
706                 {
707                 case OP_MV:
708                     if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(thisAddrType, thisAddr));
709                     break;
710                 case OP_ADD2:
711                     if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(thisAddrType, thisAddr) + GetVarData(nParamType2, nParamAddr2));
712                     break;
713                 case OP_SUB2:
714                     if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(nParamType2, nParamAddr2) - GetVarData(thisAddrType, thisAddr));
715                     break;
716
717                 default:
718                     break;
719                 }
720
721             }
722             nNextPos = 2;
723             break;
724             // 3 ??????
725         case OP_ADD3:
726         case OP_SUB3:
727         case OP_MUL:
728         case OP_DIV:
729             pBinProg3 = (stBinProg3 *)(&pBinprog[CurPos]);
730             int nParamType2, nParamAddr2;
731             int nParamType3, nParamAddr3;
732             thisAddrType = pBinProg3->nParamType1;
733             thisAddr = pBinProg3->nParamAddr1;
734             nParamType2 = pBinProg3->nParamType2;
735             nParamAddr2 = pBinProg3->nParamAddr2;
736             nParamType3 = pBinProg3->nParamType3;
737             nParamAddr3 = pBinProg3->nParamAddr3;
738             switch (thisOP)
739             {
740             case OP_ADD3:
741                 if (KMem.CurVAL) SetVarData(nParamType3, nParamAddr3, GetVarData(thisAddrType, thisAddr) + GetVarData(nParamType2, nParamAddr2));
742                 break;
743             case OP_SUB3:
744                 if (KMem.CurVAL) SetVarData(nParamType3, nParamAddr3, GetVarData(thisAddrType, thisAddr) - GetVarData(nParamType2, nParamAddr2));
745                 break;
746             case OP_MUL:
747                 if (KMem.CurVAL) {
748                     short multiplicand = GetVarData(thisAddrType, thisAddr);
749                     short multiplier = GetVarData(nParamType2, nParamAddr2);
750                     int product = multiplicand * multiplier;
751                     SetVarData(nParamType3, nParamAddr3, product);
752                     SetVarData(nParamType3, nParamAddr3 + 1, product >> 16);
753                 }
754                 break;
755             case OP_DIV:
756                 if (KMem.CurVAL) {
757                     short dividend = GetVarData(thisAddrType, thisAddr);
758                     short divisor = GetVarData(nParamType2, nParamAddr2);
759                     short quotient = dividend / divisor;
760                     short remainder = dividend % divisor;
761                     SetVarData(nParamType3, nParamAddr3, quotient);
762                     SetVarData(nParamType3, nParamAddr3 + 1, remainder);
763                 }
764                 break;
765
766             default:
767                 break;
768             }
769             nNextPos = 3;
770             break;
771
772         default:
773             break;
774         }
775         lastScanInputVal =  GetBitValue( PLCMem.ProgTrace[CurPos>>4],CurPos&0xf); //GetBitValue(KMem.WDFs);
776         SetBitValue( &PLCMem.ProgTrace[CurPos>>4],CurPos&0xf, KMem.CurVAL);
777         
778 //        lastScanInputVal =  PLCMem.ProgTrace[CurPos]; //GetBitValue(KMem.WDFs);
779 //        PLCMem.ProgTrace[CurPos] = KMem.CurVAL;
780         CurPos += nNextPos;
781     }
782     PLCMem.nScanCount++;
783     return 0;
784 }