rllib  1
rl3964r.cpp
Go to the documentation of this file.
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