|
rllib
1
|
00001 /*************************************************************************** 00002 rl3964r.cpp - description 00003 ------------------- 00004 begin : Wed Jan 14 2004 00005 copyright : (C) 2004 by Rainer Lehrig 00006 email : lehrig@t-online.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as * 00013 * published by the Free Software Foundation * 00014 * * 00015 ***************************************************************************/ 00016 #include <stdio.h> 00017 #include <stdarg.h> 00018 #include <string.h> 00019 #include "rlcutil.h" 00020 #include "rl3964r.h" 00021 #define STX 2 00022 #define ETX 3 00023 #define ENQ 5 00024 #define EOT 4 00025 #define ETB 23 00026 #define DLE 16 00027 #define NAK 21 00028 #define ACK 6 00029 00030 enum State 00031 { 00032 IDLE = 0, 00033 SENDING = 1, 00034 RECEIVING = 2, 00035 WANT_TO_SEND = 3, 00036 WANT_TO_RECEIVE = 4 00037 }; 00038 00039 static const char *statestr[] = {"idle","sending","receiving","want_to_send","want_to_receive"}; 00040 00041 static void *receiverThread(void *arg) 00042 { 00043 THREAD_PARAM *p = (THREAD_PARAM *) arg; 00044 rl3964R *d = (rl3964R *) p->user; 00045 unsigned char c; 00046 int ret,send_retry; 00047 00048 send_retry = 0; 00049 while(d->run) 00050 { 00051 c = 0x0ff; 00052 ret = d->tty.select(1000); 00053 if(ret == 1) c = d->tty.readChar(); 00054 p->thread->lock(); 00055 00056 d->dprintf("receiverThread: c=%d state=%s\n",c,statestr[d->state]); 00057 if(c==STX && d->state==IDLE) 00058 { 00059 d->dprintf("STX IDLE\n"); 00060 d->state = RECEIVING; 00061 d->dprintf("write DLE\n"); 00062 d->tty.writeChar(DLE); 00063 d->dprintf("call receive\n"); 00064 d->receive(); 00065 d->dprintf("after receive\n"); 00066 d->state = IDLE; 00067 } 00068 else if(c==STX && d->state==WANT_TO_SEND && d->priority==rl3964R::lowPriority) 00069 { 00070 d->dprintf("receiverThread: STX WANT_TO_SEND lowPriority\n"); 00071 d->state = RECEIVING; 00072 d->tty.writeChar(DLE); 00073 d->receive(); 00074 d->state = WANT_TO_SEND; 00075 } 00076 else if(c==STX && d->state==WANT_TO_SEND && d->priority==rl3964R::highPriority) 00077 { 00078 d->dprintf("receiverThread: STX WANT_TO_SEND highPriority\n"); 00079 d->tty.writeChar(NAK); 00080 d->tty.writeChar(STX); 00081 } 00082 else if(c==DLE && d->state==WANT_TO_SEND) 00083 { 00084 d->dprintf("receiverThread: DLE WANT_TO_SEND\n"); 00085 d->send(); 00086 d->state = IDLE; 00087 d->receiver.incrementSemaphore(); 00088 } 00089 else if(c==NAK) 00090 { 00091 d->dprintf("receiverThread: NAK\n"); 00092 } 00093 else if(d->state==WANT_TO_SEND) 00094 { 00095 if(send_retry < 1) 00096 { 00097 } 00098 else if(send_retry < 3) 00099 { 00100 d->tty.writeChar(STX); 00101 send_retry++; 00102 d->dprintf("receiverThread: WANT_TO_SEND send=STX retry=%d\n",send_retry+1); 00103 } 00104 else 00105 { 00106 send_retry = 0; 00107 d->dprintf("receiverThread: WANT_TO_SEND failed after 3 retries\n"); 00108 d->state = IDLE; 00109 d->receiver.incrementSemaphore(); 00110 } 00111 } 00112 else 00113 { 00114 d->dprintf("receiverThread: IDLE\n"); 00115 d->state = IDLE; 00116 } 00117 00118 p->thread->unlock(); 00119 } 00120 00121 return NULL; 00122 } 00123 00124 rl3964R::rl3964R(int _priority) 00125 { 00126 priority = _priority; 00127 readCallback = NULL; 00128 debug = 0; 00129 isOpen = 0; 00130 state = IDLE; 00131 send_result = 0; 00132 tel_receive_length = tel_send_length = -1; 00133 } 00134 00135 rl3964R::~rl3964R() 00136 { 00137 close(); 00138 } 00139 00140 int rl3964R::open(const char *devicename, int _baudrate) 00141 { 00142 int ret; 00143 00144 if(isOpen == 0) 00145 { 00146 //int openDevice(const char *devicename, int speed=B9600, int block=1, int rtscts=1, int bits=8, int stopbits=1, int parity=NONE); 00147 ret = tty.openDevice(devicename,_baudrate,1,0,8,1,rlSerial::EVEN); 00148 if(ret >= 0) 00149 { 00150 isOpen = 1; 00151 run = 1; 00152 receiver.create(receiverThread,this); 00153 } 00154 return ret; 00155 } 00156 return -1; 00157 } 00158 00159 int rl3964R::close() 00160 { 00161 if(isOpen == 1) 00162 { 00163 isOpen = 0; 00164 run = 0; 00165 dprintf("close(): cancel\n"); 00166 receiver.cancel(); 00167 dprintf("close(): closeDevice\n"); 00168 tty.closeDevice(); 00169 dprintf("close(): return\n"); 00170 return 0; 00171 } 00172 isOpen = 0; 00173 return -1; 00174 } 00175 00176 int rl3964R::setReadCallback( void (*_readCallback)(const unsigned char *buf, int len)) 00177 { 00178 readCallback = _readCallback; 00179 return 0; 00180 } 00181 00182 int rl3964R::write(const unsigned char *buf, int len) 00183 { 00184 dprintf("write() len=%d\n",len); 00185 if(len >= (int) sizeof(tel_send)) return -1; 00186 receiver.lock(); 00187 tel_send_length = len; 00188 memcpy(tel_send,buf,len); 00189 state = WANT_TO_SEND; 00190 dprintf("write() STX\n"); 00191 tty.writeChar(STX); 00192 dprintf("write() unlock\n"); 00193 receiver.unlock(); 00194 dprintf("write() waitSemaphore\n"); 00195 receiver.waitSemaphore(); 00196 dprintf("write() return len=%d\n",len); 00197 if(send_result < 0) return -1; 00198 return len; 00199 } 00200 00201 int rl3964R::send() 00202 { 00203 int i,bcc,c,ret; 00204 00205 dprintf("send()"); 00206 //bcc = STX; 00207 bcc = 0; 00208 for(i=0; i<tel_send_length; i++) 00209 { 00210 switch(tel_send[i]) 00211 { 00212 case DLE: 00213 tty.writeChar(DLE); 00214 tty.writeChar(DLE); 00215 bcc = bcc ^ DLE; 00216 bcc = bcc ^ DLE; 00217 break; 00218 default: 00219 tty.writeChar(tel_send[i]); 00220 bcc = bcc ^ tel_send[i]; 00221 break; 00222 } 00223 } 00224 tty.writeChar(DLE); 00225 bcc = bcc ^ DLE; 00226 tty.writeChar(ETX); 00227 bcc = bcc ^ ETX; 00228 tty.writeChar(bcc); 00229 ret = tty.select(1000); 00230 if(ret == 1) c = tty.readChar(); 00231 else 00232 { 00233 send_result = -1; 00234 dprintf("send(): partner was sending nothing\n"); 00235 return -1; 00236 } 00237 if(c == DLE) 00238 { 00239 send_result = 0; 00240 dprintf(" success\n"); 00241 return tel_send_length; 00242 } 00243 send_result = -1; 00244 dprintf(" failure\n"); 00245 return -1; 00246 } 00247 00248 int rl3964R::receive() 00249 { 00250 int i,c,c2,bcc,received_bcc,ret; 00251 00252 dprintf("receive()\n"); 00253 //bcc = STX; 00254 bcc = 0; 00255 i = received_bcc = 0; 00256 tel_receive[i++] = c = STX; 00257 while(c > 0 && i < (int) sizeof(tel_receive)) 00258 { 00259 ret = tty.select(1000); 00260 if(ret == 1) c = tty.readChar(); 00261 else 00262 { 00263 dprintf("receive(): partner was sending nothing\n"); 00264 return -1; 00265 } 00266 dprintf(" %x\n",c); 00267 switch(c) 00268 { 00269 case -1: 00270 case -2: 00271 return -1; 00272 case DLE: 00273 bcc = bcc ^ c; 00274 c2 = tty.readChar(); 00275 dprintf(" %x\n",c2); 00276 bcc = bcc ^ c2; 00277 if(c2 < 0) return -1; 00278 tel_receive[i++] = c2; 00279 if(c2 == ETX) 00280 { 00281 c2 = tty.readChar(); 00282 dprintf(" %x\n",c2); 00283 if(c2 < 0) return -1; 00284 tel_receive[i++] = c2; // bcc 00285 received_bcc = c2; 00286 dprintf(" bcc=%d received_bcc=%d\n",bcc,received_bcc); 00287 c = -1; 00288 } 00289 break; 00290 default: 00291 bcc = bcc ^ c; 00292 tel_receive[i++] = c; 00293 break; 00294 } 00295 } 00296 tel_receive_length = i; 00297 00298 if(bcc == received_bcc) 00299 { 00300 tty.writeChar(DLE); 00301 dprintf(" success\n"); 00302 if(readCallback != NULL) (readCallback)(&tel_receive[1],tel_receive_length-3); 00303 return tel_receive_length-3; 00304 } 00305 tty.writeChar(NAK); 00306 dprintf(" failure\n"); 00307 return -1; 00308 } 00309 00310 int rl3964R::dprintf(const char *format, ...) 00311 { 00312 char message[rl_PRINTF_LENGTH]; // should be big enough 00313 int ret; 00314 00315 if(debug != 1) return 0; 00316 va_list ap; 00317 va_start(ap,format); 00318 ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap); 00319 va_end(ap); 00320 printf("%s",message); 00321 return ret; 00322 } 00323
1.7.5.1