Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
20 | pj | 1 | /* |
2 | * Project: |
||
3 | * Parallel Port S.Ha.R.K. Project |
||
4 | * |
||
5 | * Module: |
||
6 | * ppDrv.c |
||
7 | * |
||
8 | * Description: |
||
9 | * file contents description |
||
10 | * |
||
11 | * Coordinators: |
||
12 | * Giorgio Buttazzo <giorgio@sssup.it> |
||
13 | * Paolo Gai <pj@gandalf.sssup.it> |
||
14 | * |
||
15 | * Authors: |
||
16 | * Andrea Battistotti <btandrea@libero.it> |
||
17 | * Armando Leggio <a_leggio@hotmail.com> |
||
18 | * |
||
19 | * |
||
20 | * http://www.sssup.it |
||
21 | * http://retis.sssup.it |
||
22 | * http://shark.sssup.it |
||
23 | * |
||
24 | */ |
||
25 | |||
26 | /********************************************************************************************************** |
||
27 | * Module : ppDrv.c Author : Andrea Battistotti , Armando Leggio |
||
28 | * Description: Tranfer Byte via LPT1 laplink cable... 2002 @ Pavia - |
||
29 | * GNU Copyrights */ |
||
30 | |||
31 | /* |
||
32 | * Copyright (C) 2002 Andrea Battistotti , Armando Leggio |
||
33 | * |
||
34 | * This program is free software; you can redistribute it and/or modify |
||
35 | * it under the terms of the GNU General Public License as published by |
||
36 | * the Free Software Foundation; either version 2 of the License, or |
||
37 | * (at your option) any later version. |
||
38 | * |
||
39 | * This program is distributed in the hope that it will be useful, |
||
40 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
41 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
42 | * GNU General Public License for more details. |
||
43 | * |
||
44 | * You should have received a copy of the GNU General Public License |
||
45 | * along with this program; if not, write to the Free Software |
||
46 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
47 | * |
||
48 | * CVS : $Id: ppdrv.c,v 1.1 2002-10-28 08:03:54 pj Exp $ |
||
49 | */ |
||
50 | |||
51 | |||
52 | #include <drivers/parport.h> |
||
53 | |||
54 | |||
55 | /* internal */ |
||
56 | BYTE RxBuf[PP_BUF_LEN]; /* Received bytes buffer */ |
||
57 | BYTE TxBuf[PP_BUF_LEN]; /* To transmit bytes buffer */ |
||
58 | |||
59 | unsigned int nextByteReadyToRx; /* pointer to first byte to read by ppOneByteRx(BYTE *c) ... */ |
||
60 | unsigned int nextByteReadyToTx; /* when ppbTransmit had to send a byte, send this...*/ |
||
61 | unsigned int nextByteFreeRx; /* when polling complete reading a byte, will save it in this loc...*/ |
||
62 | unsigned int nextByteFreeTx; /* when ppbTransmit had to write a byte, write it here...*/ |
||
63 | |||
64 | /* define inline macro */ |
||
65 | /* these are for cicle buffer mamagement */ |
||
66 | #define RxPointerGap (nextByteFreeRx-nextByteReadyToRx) |
||
67 | #define bytesReadyToRx ((RxPointerGap)>=0? (RxPointerGap):PP_BUF_LEN+(RxPointerGap)) |
||
68 | #define TxPointerGap (nextByteFreeTx-nextByteReadyToTx) |
||
69 | #define bytesReadyToTx ((TxPointerGap)>=0? (TxPointerGap):PP_BUF_LEN+(TxPointerGap)) |
||
70 | #define freeBytesInRxBuffer (PP_BUF_LEN-bytesReadyToRx) |
||
71 | #define freeBytesInTxBuffer (PP_BUF_LEN-bytesReadyToTx) |
||
72 | |||
73 | |||
74 | /* for pp sys msg */ |
||
75 | char SysMsg[SYS_MSG_COLS+1][SYS_MSG_LINS+1]; /* space for sys msgs... */ |
||
76 | char bufMsg[SYS_MSG_COLS+1]; /* to build msgs... */ |
||
77 | |||
78 | unsigned int nextMsgToRead; |
||
79 | unsigned int nextMsgFreeToWrite; |
||
80 | |||
81 | /* define inline macro */ |
||
82 | /* these are for cicle buffer mamagement */ |
||
83 | #define msgPointerGap (nextMsgFreeToWrite-nextMsgToRead) |
||
84 | #define msgReadyToRead ((msgPointerGap)>=0? (msgPointerGap):SYS_MSG_LINS+(msgPointerGap)) |
||
85 | #define freeMsgInBuffer (SYS_MSG_LINS-msgReadyToRead) |
||
86 | |||
87 | |||
88 | |||
89 | |||
90 | /* status ... */ |
||
91 | enum ppReadingAvailableStates |
||
92 | { |
||
93 | ppNoAllowReading, /* writing is on...*/ |
||
94 | ppNoReading, |
||
95 | ppWaitingDR_Nibble1, |
||
96 | ppWaitingRTS_Nibble2, |
||
97 | ppWaitingDR_Nibble2, |
||
98 | }; |
||
99 | |||
100 | enum ppWritingAvailableStates |
||
101 | { |
||
102 | ppNoAllowWriting, /* reading is on...*/ |
||
103 | ppNoWriting, |
||
104 | ppWaitingOTS_Nibble1, |
||
105 | ppWaitingER_Nibble1, |
||
106 | ppWaitingOTS_Nibble2, |
||
107 | ppWaitingER_Nibble2 |
||
108 | }; |
||
109 | |||
110 | |||
111 | int ppStatusReading; |
||
112 | int ppStatusWriting; |
||
113 | BYTE ppReceivingByte; |
||
114 | BYTE ppTransmittingByte; |
||
115 | |||
116 | |||
117 | #if PP_STATS == 1 |
||
118 | /* for internal statistic ...if activate...*/ |
||
119 | long statReading[ppWaitingDR_Nibble2+1]; |
||
120 | long statWriting[ppWaitingER_Nibble2+1]; |
||
121 | #endif |
||
122 | |||
123 | |||
124 | |||
125 | /*********************************************/ |
||
126 | /* sys msg managment */ |
||
127 | /*********************************************/ |
||
128 | |||
129 | int ppReadSysMsg(char * buf) |
||
130 | { |
||
131 | if (!msgReadyToRead) /* there is nothing to read...*/ |
||
132 | { |
||
133 | return (PP_NOSYSMSG_EXC); |
||
134 | } |
||
135 | else |
||
136 | {int i=0; |
||
137 | while (i<SYS_MSG_COLS && SysMsg[nextMsgToRead][i]) /* !='\0'...*/ |
||
138 | *buf++=SysMsg[nextMsgToRead][i++]; /* read char */ |
||
139 | |||
140 | *buf='\0'; |
||
141 | nextMsgToRead=++nextMsgToRead%SYS_MSG_LINS; /* circular buffer increment */ |
||
142 | return (PP_SYSMSG_OK); |
||
143 | } |
||
144 | } |
||
145 | |||
146 | |||
147 | |||
148 | int ppWriteSysMsg(char * buf, ...) |
||
149 | { |
||
150 | char * pbufMsg=bufMsg; |
||
151 | va_list args; |
||
152 | bufMsg[0]='\0'; |
||
153 | va_start(args, buf); |
||
154 | vsprintf(bufMsg,buf,args); /* Not garatee msg len... */ |
||
155 | va_end(args); |
||
156 | |||
157 | |||
158 | if (freeMsgInBuffer < 1) |
||
159 | { |
||
160 | return (PP_NOFREEMSG_EXC); |
||
161 | } |
||
162 | else |
||
163 | {int i=0; |
||
164 | while ((i<SYS_MSG_COLS) && (*pbufMsg) ) /* !='\0'...*/ |
||
165 | SysMsg[nextMsgFreeToWrite][i++]=*pbufMsg++; |
||
166 | |||
167 | SysMsg[nextMsgFreeToWrite][i-1]='\n'; |
||
168 | SysMsg[nextMsgFreeToWrite][i]='\0'; |
||
169 | nextMsgFreeToWrite=++nextMsgFreeToWrite%SYS_MSG_LINS; /* circular buffer pointer increment */ |
||
170 | return (PP_SYSMSG_OK); |
||
171 | } |
||
172 | } |
||
173 | |||
174 | |||
175 | /******************************************/ |
||
176 | /* Inizialization: this is NRT task... */ |
||
177 | /******************************************/ |
||
178 | |||
179 | void ppInitDrv(void (*pf)(char *)) |
||
180 | { |
||
181 | /* set to zero all pointer & buffer & status... */ |
||
182 | |||
183 | |||
184 | while(ppNRTOpenComm()!=TRUE) // not real-time.... |
||
185 | { |
||
186 | if (pf!=NULL) (*pf)("Waiting Open Communcation...\n"); |
||
187 | ppSendER(); |
||
188 | } |
||
189 | if (pf!=NULL) (*pf)("Open Communcation OK!\n"); |
||
190 | } |
||
191 | |||
192 | |||
193 | /******************************************/ |
||
194 | /* TX RX funtions... */ |
||
195 | /******************************************/ |
||
196 | |||
197 | int ppRxOneByte(BYTE *c) |
||
198 | { |
||
199 | if (!bytesReadyToRx) /* there is nothing to read...*/ |
||
200 | { |
||
201 | return (PP_COMM_NOREADYBYTES_EXC); |
||
202 | } |
||
203 | else |
||
204 | { |
||
205 | *c=RxBuf[nextByteReadyToRx]; /* read byte */ |
||
206 | nextByteReadyToRx=++nextByteReadyToRx%PP_BUF_LEN; /* circular buffer increment */ |
||
207 | return (PP_COMM_OK); |
||
208 | } |
||
209 | } |
||
210 | |||
211 | |||
212 | int ppTxOneByte(BYTE c) |
||
213 | { |
||
214 | if (freeBytesInTxBuffer < 1) |
||
215 | { |
||
216 | return (PP_COMM_NOFREEBYTES_EXC); |
||
217 | } |
||
218 | else |
||
219 | { |
||
220 | TxBuf[nextByteFreeTx]=c; |
||
221 | nextByteFreeTx=++nextByteFreeTx%PP_BUF_LEN; /* circular buffer pointer increment */ |
||
222 | |||
223 | return (PP_COMM_OK); |
||
224 | } |
||
225 | } |
||
226 | |||
227 | int ppTxBytes(BYTE * c, unsigned int nbyte) |
||
228 | { |
||
229 | if (freeBytesInTxBuffer<nbyte) /* if there are less than nbyte return nothing...*/ |
||
230 | { |
||
231 | return (PP_COMM_NOFREEBYTES_EXC); |
||
232 | } |
||
233 | else |
||
234 | { unsigned int i; |
||
235 | for (i=0;i<nbyte;i++) |
||
236 | { |
||
237 | TxBuf[nextByteFreeTx]=*c++; |
||
238 | nextByteFreeTx=++nextByteFreeTx%PP_BUF_LEN; /* circular buffer pointer increment */ |
||
239 | } |
||
240 | |||
241 | return (PP_COMM_OK); |
||
242 | } |
||
243 | } |
||
244 | |||
245 | |||
246 | |||
247 | int ppRxBytes(BYTE * c, unsigned int nbyte) |
||
248 | { |
||
249 | |||
250 | if (bytesReadyToRx<nbyte) /* if there are less than nbyte return nothing...*/ |
||
251 | { |
||
252 | return (PP_COMM_NOREADYBYTES_EXC); |
||
253 | } |
||
254 | else |
||
255 | { unsigned int i; |
||
256 | |||
257 | for (i=0;i<nbyte;i++) |
||
258 | { |
||
259 | *c++=RxBuf[nextByteReadyToRx]; /* read byte */ |
||
260 | |||
261 | #if PP_DEBUG == 1 |
||
262 | ppWriteSysMsg("Received value: %i %i of %i \n",RxBuf[nextByteReadyToRx],i,nbyte); |
||
263 | #endif |
||
264 | |||
265 | nextByteReadyToRx=++nextByteReadyToRx%PP_BUF_LEN; /* circular buffer increment */ |
||
266 | } |
||
267 | |||
268 | return (PP_COMM_OK); |
||
269 | } |
||
270 | } |
||
271 | |||
272 | |||
273 | |||
274 | |||
275 | /* polling server ... */ |
||
276 | TASK ppPollingSvr(void *arg) |
||
277 | { |
||
278 | BYTE port; |
||
279 | nextByteReadyToRx=0; |
||
280 | nextByteReadyToTx=0; |
||
281 | nextByteFreeRx=0; |
||
282 | nextByteFreeTx=0; |
||
283 | |||
284 | nextMsgToRead=0; |
||
285 | nextMsgFreeToWrite=0; |
||
286 | |||
287 | |||
288 | ppStatusReading=ppNoReading; |
||
289 | ppStatusWriting=ppNoWriting; |
||
290 | |||
291 | ppWriteSysMsg("Polling Server started...\n"); |
||
292 | |||
293 | task_endcycle(); |
||
294 | |||
295 | while (1) |
||
296 | { |
||
297 | |||
298 | /* case ppReading: read ... */ |
||
299 | switch (ppStatusReading) |
||
300 | { |
||
301 | case ppNoAllowReading: break; |
||
302 | |||
303 | case ppNoReading: |
||
304 | |||
305 | ppStatusWriting=ppNoWriting; |
||
306 | |||
307 | if(!ppIsRTS()) break; |
||
308 | ppSendOTS(); /* Set Ok To Send - the other one can send... */ |
||
309 | |||
310 | #if PP_DEBUG == 1 |
||
311 | ppWriteSysMsg(" %i : Received RTS...\n", ppStatusReading); |
||
312 | #endif |
||
313 | |||
314 | ppStatusWriting=ppNoAllowWriting; |
||
315 | ppStatusReading=ppWaitingDR_Nibble1; |
||
316 | |||
317 | case ppWaitingDR_Nibble1: |
||
318 | |||
319 | #if PP_STATS == 1 /* for internal statistic ...*/ |
||
320 | statReading[ppStatusReading]++; |
||
321 | #endif |
||
322 | |||
323 | |||
324 | |||
325 | #if PP_DEBUG == 1 |
||
326 | ppWriteSysMsg("Send OTS\n"); |
||
327 | ppWriteSysMsg("Waiting DR Nibble1\n"); |
||
328 | #endif |
||
329 | |||
330 | if(!ppIsDR()) break; /* data no ready: read it next period...*/ |
||
331 | port = inp(RX_PORT); /* read nibble */ |
||
332 | ppSendER(); /* send a End Read */ |
||
333 | |||
334 | ppReceivingByte = (port >> 3); /* read LSN */ |
||
335 | ppStatusReading=ppWaitingRTS_Nibble2; |
||
336 | |||
337 | case ppWaitingRTS_Nibble2: |
||
338 | #if PP_STATS == 1 /* for internal statistic ...*/ |
||
339 | statReading[ppStatusReading]++; |
||
340 | #endif |
||
341 | |||
342 | #if PP_DEBUG == 1 |
||
343 | |||
344 | ppWriteSysMsg("Received DR Nibble1\n"); |
||
345 | ppWriteSysMsg("Send ER Nibble1\n"); |
||
346 | ppWriteSysMsg("Waiting RTS Nibble2\n"); |
||
347 | #endif |
||
348 | |||
349 | if(!ppIsRTS()) break; /* */ |
||
350 | ppSendOTS(); /* Ok To Send - the other one can send... */ |
||
351 | |||
352 | ppStatusReading=ppWaitingDR_Nibble2; |
||
353 | |||
354 | case ppWaitingDR_Nibble2: |
||
355 | #if PP_STATS == 1 /* for internal statistic ...*/ |
||
356 | statReading[ppStatusReading]++; |
||
357 | #endif |
||
358 | #if PP_DEBUG == 1 |
||
359 | ppWriteSysMsg("Received RTS Nibble2\n"); |
||
360 | ppWriteSysMsg("Send OTS Nibble2\n"); |
||
361 | ppWriteSysMsg("Waiting DR Nibble2\n"); |
||
362 | #endif |
||
363 | |||
364 | if(!ppIsDR()) break; |
||
365 | port = inp(RX_PORT); /* read nibble */ |
||
366 | ppSendER(); /* send a End Read */ |
||
367 | |||
368 | |||
369 | #if PP_DEBUG == 1 |
||
370 | ppWriteSysMsg("Received DR Nibble2\n"); |
||
371 | ppWriteSysMsg("Read Nibble2\n"); |
||
372 | ppWriteSysMsg("Send ER Nibble2\n"); |
||
373 | #endif |
||
374 | |||
375 | |||
376 | |||
377 | ppReceivingByte = (ppReceivingByte & ~MSN); /* set to zero c MSN */ |
||
378 | ppReceivingByte = (ppReceivingByte | ((port >> 3) << 4)); /* read MSN */ |
||
379 | |||
380 | |||
381 | /* here is possible insert some ctrl ... */ |
||
382 | |||
383 | |||
384 | /* byte is ok, so now make it available to ppRxOneByte() */ |
||
385 | |||
386 | RxBuf[nextByteFreeRx]=ppReceivingByte; |
||
387 | nextByteFreeRx=++nextByteFreeRx%PP_BUF_LEN; /* circular buffer pointer increment */ |
||
388 | |||
389 | #if PP_STATS == 1 |
||
390 | ppWriteSysMsg("Trasmission :\n"); |
||
391 | ppWriteSysMsg("W_DR_1 : %d\n",statReading[ppWaitingDR_Nibble1]); |
||
392 | ppWriteSysMsg("W_RTS_2 : %d\n",statReading[ppWaitingRTS_Nibble2]); |
||
393 | ppWriteSysMsg("W_DR_2 : %d\n",statReading[ppWaitingDR_Nibble2]); |
||
394 | ppWriteSysMsg("Received byte : %i\n",ppReceivingByte); |
||
395 | statReading[ppWaitingDR_Nibble1]=0; |
||
396 | statReading[ppWaitingRTS_Nibble2]=0; |
||
397 | statReading[ppWaitingDR_Nibble2]=0; |
||
398 | #endif |
||
399 | /* end reading so reset status... */ |
||
400 | |||
401 | ppStatusReading=ppNoReading; |
||
402 | //ppStatusWriting=ppNoWriting; |
||
403 | break; |
||
404 | } |
||
405 | |||
406 | |||
407 | /* case Writing: can only if this cycle not is reading... */ |
||
408 | switch (ppStatusWriting) |
||
409 | { |
||
410 | |||
411 | case ppNoAllowWriting: break; |
||
412 | |||
413 | case ppNoWriting: |
||
414 | |||
415 | ppStatusReading=ppNoReading; |
||
416 | |||
417 | if(!bytesReadyToTx) |
||
418 | { |
||
419 | break; |
||
420 | #if PP_DEBUG == 1 |
||
421 | ppWriteSysMsg("Writin break\n"); |
||
422 | #endif |
||
423 | } |
||
424 | else |
||
425 | { |
||
426 | #if PP_DEBUG == 1 |
||
427 | ppWriteSysMsg("NO Writin break\n"); |
||
428 | ppWriteSysMsg("TX Gap: %i \n",TxPointerGap); |
||
429 | ppWriteSysMsg("nextByteFreeTx: %i\n",nextByteFreeTx); |
||
430 | ppWriteSysMsg("nextByteReadyToTx: %i\n",nextByteReadyToTx); |
||
431 | #endif |
||
432 | } |
||
433 | |||
434 | ppSendRTS(); /* Set On RequestToSend bit */ |
||
435 | |||
436 | ppTransmittingByte=TxBuf[nextByteReadyToTx]; |
||
437 | |||
438 | #if PP_DEBUG == 1 |
||
439 | ppWriteSysMsg("pllsvr: ppTransmittingByte : %i %c \n",ppTransmittingByte,ppTransmittingByte); |
||
440 | #endif |
||
441 | |||
442 | |||
443 | port = inp(TX_PORT) & (~TX_DATA); /* set to zero trasmission bits */ |
||
444 | port = port | (ppTransmittingByte & LSN); /* set bits 0..3 with LSN */ |
||
445 | |||
446 | ppStatusWriting=ppWaitingOTS_Nibble1; |
||
447 | ppStatusReading=ppNoAllowWriting; |
||
448 | |||
449 | case ppWaitingOTS_Nibble1: |
||
450 | #if PP_STATS == 1 |
||
451 | statWriting[ppStatusWriting]++; |
||
452 | #endif |
||
453 | |||
454 | #if PP_DEBUG == 1 |
||
455 | ppWriteSysMsg(" Send RTS Nibble1\n"); |
||
456 | ppWriteSysMsg(" Waiting OTS Nibble1\n"); |
||
457 | #endif |
||
458 | if(!ppIsOTS()) break; |
||
459 | outp(TX_PORT,port); /* send nibble 1 */ |
||
460 | ppSendDR(); /* set on Data Ready bit */ |
||
461 | |||
462 | |||
463 | ppStatusWriting=ppWaitingER_Nibble1; |
||
464 | |||
465 | |||
466 | case ppWaitingER_Nibble1: |
||
467 | #if PP_STATS == 1 |
||
468 | statWriting[ppStatusWriting]++; |
||
469 | #endif |
||
470 | |||
471 | #if PP_DEBUG == 1 |
||
472 | ppWriteSysMsg(" Send Nibble1\n"); |
||
473 | ppWriteSysMsg(" Send DR Nibble1\n"); |
||
474 | ppWriteSysMsg(" Waiting ER Nibble1\n"); |
||
475 | #endif |
||
476 | |||
477 | if(!ppIsER()) break; |
||
478 | |||
479 | ppSendRTS(); /* send trasmission request */ |
||
480 | |||
481 | port = inp(TX_PORT) & (~TX_DATA); /* set to zero bit trasmission bits */ |
||
482 | port = port | (ppTransmittingByte >> 4); /* set bits 0..3 with MSN */ |
||
483 | |||
484 | ppStatusWriting=ppWaitingOTS_Nibble2; |
||
485 | |||
486 | case ppWaitingOTS_Nibble2: |
||
487 | |||
488 | #if PP_STATS == 1 |
||
489 | statWriting[ppStatusWriting]++; |
||
490 | #endif |
||
491 | |||
492 | #if PP_DEBUG == 1 |
||
493 | ppWriteSysMsg(" Received ER Nibble1\n"); |
||
494 | ppWriteSysMsg(" Send RTS Nibble2\n"); |
||
495 | ppWriteSysMsg(" Waiting OTS Nibble2\n"); |
||
496 | #endif |
||
497 | |||
498 | |||
499 | if(!ppIsOTS()) break; |
||
500 | outp(TX_PORT,port); /* send nibble 2 */ |
||
501 | ppSendDR(); /* set on Data Ready bit */ |
||
502 | |||
503 | ppStatusWriting=ppWaitingER_Nibble2; |
||
504 | |||
505 | case ppWaitingER_Nibble2: |
||
506 | #if PP_STATS == 1 |
||
507 | statWriting[ppStatusWriting]++; |
||
508 | #endif |
||
509 | |||
510 | #if PP_DEBUG == 1 |
||
511 | ppWriteSysMsg(" Received OTS Nibble2\n"); |
||
512 | ppWriteSysMsg(" Write Nibble2\n"); |
||
513 | ppWriteSysMsg(" Send DR Nibble2\n"); |
||
514 | ppWriteSysMsg(" Waiting ER Nibble2\n"); |
||
515 | #endif |
||
516 | |||
517 | if(!ppIsER()) break; |
||
518 | |||
519 | /* byte is ok, so move pointer to next byte to be send... */ |
||
520 | nextByteReadyToTx=++nextByteReadyToTx%PP_BUF_LEN; /* circular buffer pointer increment */ |
||
521 | |||
522 | #if PP_STATS == 1 |
||
523 | ppWriteSysMsg("Reception :\n"); |
||
524 | ppWriteSysMsg("W_OTS_1 : %ld\n",statWriting[ppWaitingOTS_Nibble1]); |
||
525 | ppWriteSysMsg("W_ER_2 : %ld\n",statWriting[ppWaitingER_Nibble2]); |
||
526 | ppWriteSysMsg("W_OTS_2 : %ld\n",statWriting[ppWaitingOTS_Nibble2]); |
||
527 | statWriting[ppWaitingOTS_Nibble1]=0; |
||
528 | statWriting[ppWaitingER_Nibble2]=0; |
||
529 | statWriting[ppWaitingOTS_Nibble2]=0; |
||
530 | #endif |
||
531 | |||
532 | /* end writing. so reset status... */ |
||
533 | ppStatusReading=ppNoReading; |
||
534 | ppStatusWriting=ppNoWriting; |
||
535 | } |
||
536 | |||
537 | task_endcycle(); |
||
538 | } |
||
539 | return (0); |
||
540 | } |
||
541 | |||
542 | |||
543 |