19 #include <string.h> |
19 #include <string.h> |
20 |
20 |
21 /* The fifo (fixed size, as number of FB is fixed) */ |
21 /* The fifo (fixed size, as number of FB is fixed) */ |
22 static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d]; |
22 static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d]; |
23 /* Producer and consumer cursors */ |
23 /* Producer and consumer cursors */ |
24 static long Current_PLC_EvalFB; |
24 static int Current_PLC_EvalFB; |
25 static long Current_Python_EvalFB; |
25 static int Current_Python_EvalFB; |
26 |
26 |
27 /* A global IEC-Python gateway state, for use inside python_eval FBs*/ |
27 /* A global IEC-Python gateway state, for use inside python_eval FBs*/ |
28 static int PythonState; |
28 static int PythonState; |
29 #define PYTHON_LOCKED_BY_PYTHON 0 |
29 #define PYTHON_LOCKED_BY_PYTHON 0 |
30 #define PYTHON_LOCKED_BY_PLC 1 |
30 #define PYTHON_LOCKED_BY_PLC 1 |
83 * Called by the PLC, each time a python_eval |
83 * Called by the PLC, each time a python_eval |
84 * FB instance is executed |
84 * FB instance is executed |
85 */ |
85 */ |
86 void __PythonEvalFB(PYTHON_EVAL* data__) |
86 void __PythonEvalFB(PYTHON_EVAL* data__) |
87 { |
87 { |
|
88 /* detect rising edge on TRIG */ |
|
89 if(data__->TRIG && !data__->TRIGM1 && data__->TRIGGED == 0){ |
|
90 /* mark as trigged */ |
|
91 data__->TRIGGED = 1; |
|
92 /* make a safe copy of the code */ |
|
93 data__->PREBUFFER = data__->CODE; |
|
94 } |
|
95 /* retain value for next detection */ |
|
96 data__->TRIGM1 = data__->TRIG; |
|
97 |
88 /* python thread is not in ? */ |
98 /* python thread is not in ? */ |
89 if( PythonState & PYTHON_LOCKED_BY_PLC){ |
99 if( PythonState & PYTHON_LOCKED_BY_PLC){ |
90 /* Rising edge on TRIG */ |
100 /* got the order to act */ |
91 if(data__->TRIG && !data__->TRIGM1 && |
101 if(data__->TRIGGED == 1 && |
92 /* and not already being processed */ |
102 /* and not already being processed */ |
93 data__->STATE == PYTHON_FB_FREE) |
103 data__->STATE == PYTHON_FB_FREE) |
94 { |
104 { |
95 /* Get a new line */ |
|
96 Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d; |
|
97 /* Enter the block in the fifo |
105 /* Enter the block in the fifo |
98 /* Don't have to check if fifo cell is free |
106 /* Don't have to check if fifo cell is free |
99 * as fifo size == FB count, and a FB cannot |
107 * as fifo size == FB count, and a FB cannot |
100 * be requested twice */ |
108 * be requested twice */ |
101 EvalFBs[Current_PLC_EvalFB] = data__; |
109 EvalFBs[Current_PLC_EvalFB] = data__; |
102 /* copy CODE in variable into BUFFER local*/ |
110 /* copy into BUFFER local*/ |
103 data__->BUFFER = data__->CODE; |
111 data__->BUFFER = data__->PREBUFFER; |
104 /* Set ACK pin to low so that we can set a rising edge on result */ |
112 /* Set ACK pin to low so that we can set a rising edge on result */ |
105 data__->ACK = 0; |
113 data__->ACK = 0; |
106 /* Mark FB busy */ |
114 /* Mark FB busy */ |
107 data__->STATE = PYTHON_FB_REQUESTED; |
115 data__->STATE = PYTHON_FB_REQUESTED; |
108 /* Have to wakeup python thread in case he was asleep */ |
116 /* Have to wakeup python thread in case he was asleep */ |
109 PythonState |= PYTHON_MUSTWAKEUP; |
117 PythonState |= PYTHON_MUSTWAKEUP; |
110 //printf("__PythonEvalFB push %%*s\n",data__->BUFFER.len, data__->BUFFER.body); |
118 //printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body); |
|
119 /* Get a new line */ |
|
120 Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d; |
111 }else if(data__->STATE == PYTHON_FB_ANSWERED){ |
121 }else if(data__->STATE == PYTHON_FB_ANSWERED){ |
|
122 /* Copy buffer content into result*/ |
112 data__->RESULT = data__->BUFFER; |
123 data__->RESULT = data__->BUFFER; |
|
124 /* signal result presece to PLC*/ |
113 data__->ACK = 1; |
125 data__->ACK = 1; |
|
126 /* Mark as free */ |
114 data__->STATE = PYTHON_FB_FREE; |
127 data__->STATE = PYTHON_FB_FREE; |
115 //printf("__PythonEvalFB pop %%*s\n",data__->BUFFER.len, data__->BUFFER.body); |
128 /* mark as not trigged */ |
|
129 data__->TRIGGED = 0; |
|
130 //printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body); |
116 } |
131 } |
117 /* retain value for trig |
|
118 * do this only when PYTHON_LOCKED_BY_PLC |
|
119 * to avoid missed rising edge due to asynchronism */ |
|
120 data__->TRIGM1 = data__->TRIG; |
|
121 } |
132 } |
122 } |
133 } |
123 |
134 |
124 char* PythonIterator(char* result) |
135 char* PythonIterator(char* result) |
125 { |
136 { |
151 EvalFBs[Current_Python_EvalFB] = NULL; |
162 EvalFBs[Current_Python_EvalFB] = NULL; |
152 /* Mark block as answered */ |
163 /* Mark block as answered */ |
153 data__->STATE = PYTHON_FB_ANSWERED; |
164 data__->STATE = PYTHON_FB_ANSWERED; |
154 /* Get a new line */ |
165 /* Get a new line */ |
155 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
166 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
|
167 //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); |
156 } |
168 } |
157 /* while next slot is empty */ |
169 /* while next slot is empty */ |
158 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
170 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
159 /* or doesn't contain command */ |
171 /* or doesn't contain command */ |
160 data__->STATE != PYTHON_FB_REQUESTED) |
172 data__->STATE != PYTHON_FB_REQUESTED) |