88 * FB instance is executed |
88 * FB instance is executed |
89 */ |
89 */ |
90 void __PythonEvalFB(int poll, PYTHON_EVAL* data__) |
90 void __PythonEvalFB(int poll, PYTHON_EVAL* data__) |
91 { |
91 { |
92 /* detect rising edge on TRIG to trigger evaluation */ |
92 /* detect rising edge on TRIG to trigger evaluation */ |
93 if(((data__->TRIG && !data__->TRIGM1) || |
93 if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) || |
94 /* polling is equivalent to trig on value rather than on rising edge*/ |
94 /* polling is equivalent to trig on value rather than on rising edge*/ |
95 (poll && data__->TRIG )) && |
95 (poll && __GET_VAR(data__->TRIG) )) && |
96 /* trig only if not already trigged */ |
96 /* trig only if not already trigged */ |
97 data__->TRIGGED == 0){ |
97 __GET_VAR(data__->TRIGGED) == 0){ |
98 /* mark as trigged */ |
98 /* mark as trigged */ |
99 data__->TRIGGED = 1; |
99 __SET_VAR(data__->TRIGGED, 1); |
100 /* make a safe copy of the code */ |
100 /* make a safe copy of the code */ |
101 data__->PREBUFFER = data__->CODE; |
101 __SET_VAR(data__->PREBUFFER, __GET_VAR(data__->CODE)); |
102 } |
102 } |
103 /* retain value for next rising edge detection */ |
103 /* retain value for next rising edge detection */ |
104 data__->TRIGM1 = data__->TRIG; |
104 __SET_VAR(data__->TRIGM1, __GET_VAR(data__->TRIG)); |
105 |
105 |
106 /* python thread is not in ? */ |
106 /* python thread is not in ? */ |
107 if( PythonState & PYTHON_LOCKED_BY_PLC){ |
107 if( PythonState & PYTHON_LOCKED_BY_PLC){ |
108 /* if some answer are waiting, publish*/ |
108 /* if some answer are waiting, publish*/ |
109 if(data__->STATE == PYTHON_FB_ANSWERED){ |
109 if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){ |
110 /* Copy buffer content into result*/ |
110 /* Copy buffer content into result*/ |
111 data__->RESULT = data__->BUFFER; |
111 __SET_VAR(data__->RESULT, __GET_VAR(data__->BUFFER)); |
112 /* signal result presece to PLC*/ |
112 /* signal result presece to PLC*/ |
113 data__->ACK = 1; |
113 __SET_VAR(data__->ACK, 1); |
114 /* Mark as free */ |
114 /* Mark as free */ |
115 data__->STATE = PYTHON_FB_FREE; |
115 __SET_VAR(data__->STATE, PYTHON_FB_FREE); |
116 /* mark as not trigged */ |
116 /* mark as not trigged */ |
117 if(!poll) |
117 if(!poll) |
118 data__->TRIGGED = 0; |
118 __SET_VAR(data__->TRIGGED, 0); |
119 /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ |
119 /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ |
120 }else if(poll){ |
120 }else if(poll){ |
121 /* when in polling, no answer == ack down */ |
121 /* when in polling, no answer == ack down */ |
122 data__->ACK = 0; |
122 __SET_VAR(data__->ACK, 0); |
123 } |
123 } |
124 /* got the order to act ?*/ |
124 /* got the order to act ?*/ |
125 if(data__->TRIGGED == 1 && |
125 if(__GET_VAR(data__->TRIGGED) == 1 && |
126 /* and not already being processed */ |
126 /* and not already being processed */ |
127 data__->STATE == PYTHON_FB_FREE) |
127 __GET_VAR(data__->STATE) == PYTHON_FB_FREE) |
128 { |
128 { |
129 /* Enter the block in the fifo |
129 /* Enter the block in the fifo |
130 /* Don't have to check if fifo cell is free |
130 /* Don't have to check if fifo cell is free |
131 * as fifo size == FB count, and a FB cannot |
131 * as fifo size == FB count, and a FB cannot |
132 * be requested twice */ |
132 * be requested twice */ |
133 EvalFBs[Current_PLC_EvalFB] = data__; |
133 EvalFBs[Current_PLC_EvalFB] = data__; |
134 /* copy into BUFFER local*/ |
134 /* copy into BUFFER local*/ |
135 data__->BUFFER = data__->PREBUFFER; |
135 __SET_VAR(data__->BUFFER, __GET_VAR(data__->PREBUFFER)); |
136 /* Set ACK pin to low so that we can set a rising edge on result */ |
136 /* Set ACK pin to low so that we can set a rising edge on result */ |
137 if(!poll){ |
137 if(!poll){ |
138 /* when not polling, a new answer imply reseting ack*/ |
138 /* when not polling, a new answer imply reseting ack*/ |
139 data__->ACK = 0; |
139 __SET_VAR(data__->ACK, 0); |
140 }else{ |
140 }else{ |
141 /* when in polling, acting reset trigger */ |
141 /* when in polling, acting reset trigger */ |
142 data__->TRIGGED = 0; |
142 __SET_VAR(data__->TRIGGED, 0); |
143 } |
143 } |
144 /* Mark FB busy */ |
144 /* Mark FB busy */ |
145 data__->STATE = PYTHON_FB_REQUESTED; |
145 __SET_VAR(data__->STATE, PYTHON_FB_REQUESTED); |
146 /* Have to wakeup python thread in case he was asleep */ |
146 /* Have to wakeup python thread in case he was asleep */ |
147 PythonState |= PYTHON_MUSTWAKEUP; |
147 PythonState |= PYTHON_MUSTWAKEUP; |
148 /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ |
148 /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/ |
149 /* Get a new line */ |
149 /* Get a new line */ |
150 Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d; |
150 Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d; |
160 /* take python mutex to prevent changing PLC data while PLC running */ |
160 /* take python mutex to prevent changing PLC data while PLC running */ |
161 LockPython(); |
161 LockPython(); |
162 /* Get current FB */ |
162 /* Get current FB */ |
163 data__ = EvalFBs[Current_Python_EvalFB]; |
163 data__ = EvalFBs[Current_Python_EvalFB]; |
164 if(data__ && /* may be null at first run */ |
164 if(data__ && /* may be null at first run */ |
165 data__->STATE == PYTHON_FB_PROCESSING){ /* some answer awaited*/ |
165 __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/ |
166 /* If result not None */ |
166 /* If result not None */ |
167 if(result){ |
167 if(result){ |
168 /* Get results len */ |
168 /* Get results len */ |
169 data__->BUFFER.len = strlen(result); |
169 __SET_VAR(data__->BUFFER, strlen(result), .len); |
170 /* prevent results overrun */ |
170 /* prevent results overrun */ |
171 if(data__->BUFFER.len > STR_MAX_LEN) |
171 if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN) |
172 { |
172 { |
173 data__->BUFFER.len = STR_MAX_LEN; |
173 __SET_VAR(data__->BUFFER, STR_MAX_LEN, .len ); |
174 /* TODO : signal error */ |
174 /* TODO : signal error */ |
175 } |
175 } |
176 /* Copy results to buffer */ |
176 /* Copy results to buffer */ |
177 strncpy(data__->BUFFER.body, result, data__->BUFFER.len); |
177 strncpy(__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len)); |
178 }else{ |
178 }else{ |
179 data__->BUFFER.len = 0; |
179 __SET_VAR(data__->BUFFER, 0, .len); |
180 } |
180 } |
181 /* remove block from fifo*/ |
181 /* remove block from fifo*/ |
182 EvalFBs[Current_Python_EvalFB] = NULL; |
182 EvalFBs[Current_Python_EvalFB] = NULL; |
183 /* Mark block as answered */ |
183 /* Mark block as answered */ |
184 data__->STATE = PYTHON_FB_ANSWERED; |
184 __SET_VAR(data__->STATE, PYTHON_FB_ANSWERED); |
185 /* Get a new line */ |
185 /* Get a new line */ |
186 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
186 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
187 //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); |
187 //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); |
188 } |
188 } |
189 /* while next slot is empty */ |
189 /* while next slot is empty */ |
190 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
190 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
191 /* or doesn't contain command */ |
191 /* or doesn't contain command */ |
192 data__->STATE != PYTHON_FB_REQUESTED) |
192 __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED) |
193 { |
193 { |
194 UnLockPython(); |
194 UnLockPython(); |
195 /* wait next FB to eval */ |
195 /* wait next FB to eval */ |
196 //printf("PythonIterator wait\n"); |
196 //printf("PythonIterator wait\n"); |
197 if(WaitPythonCommands()) return NULL; |
197 if(WaitPythonCommands()) return NULL; |
198 /*emergency exit*/ |
198 /*emergency exit*/ |
199 if(PythonState & PYTHON_FINISHED) return NULL; |
199 if(PythonState & PYTHON_FINISHED) return NULL; |
200 LockPython(); |
200 LockPython(); |
201 } |
201 } |
202 /* Mark block as processing */ |
202 /* Mark block as processing */ |
203 data__->STATE = PYTHON_FB_PROCESSING; |
203 __SET_VAR(data__->STATE, PYTHON_FB_PROCESSING); |
204 //printf("PythonIterator\n"); |
204 //printf("PythonIterator\n"); |
205 /* make BUFFER a null terminated string */ |
205 /* make BUFFER a null terminated string */ |
206 data__->BUFFER.body[data__->BUFFER.len] = 0; |
206 __SET_VAR(data__->BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]); |
207 /* next command is BUFFER */ |
207 /* next command is BUFFER */ |
208 next_command = data__->BUFFER.body; |
208 next_command = __GET_VAR(data__->BUFFER, .body); |
209 /* free python mutex */ |
209 /* free python mutex */ |
210 UnLockPython(); |
210 UnLockPython(); |
211 /* return the next command to eval */ |
211 /* return the next command to eval */ |
212 return next_command; |
212 return next_command; |
213 } |
213 } |