packet.cc

00001 // -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:1; -*-
00002 
00027 #include <stdio.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #include "packet.h"
00031 #include <unistd.h>
00032 #include <sys/select.h>
00033 #include <sys/time.h>
00034 #include <stdlib.h> /* for exit() */
00035 //#include <sys/poll.h>
00036 
00037 #include "erratic.h"
00038 
00039 void ErraticPacket::Print() {
00040         if (packet) {
00041                 printf("\"");
00042                 for(int i=0;i<size;i++) {
00043                         printf("%u ", packet[i]);
00044                 }
00045                 puts("\"");
00046         }
00047 }
00048 
00049 void ErraticPacket::PrintHex() {
00050         if (packet) {
00051                 printf("\"Hex: ");
00052                 for(int i=0;i<size;i++) {
00053                         printf("%.2x ", packet[i]);
00054                 }
00055                 puts("\"");
00056         }
00057 }
00058 
00059 
00060 bool ErraticPacket::Check() {
00061         uint16_t chksum = CalcChkSum();
00062         uint16_t received_chksum = packet[size-2] << 8 | packet[size-1];
00063 
00064         if ( chksum == received_chksum ) 
00065                 {
00066                         if (debug_mode) 
00067                         {
00068                                 printf("Good packet: ");
00069                                 PrintHex();
00070                         }
00071                         return(true);
00072                 }
00073 
00074         if (debug_mode) {
00075                 printf("This packet failed checksum control (%i instead of %i): ", received_chksum, chksum);
00076                 PrintHex();
00077         }
00078         
00079         return(false);
00080 }
00081 
00082 uint16_t ErraticPacket::CalcChkSum() {
00083         uint8_t *buffer = &packet[3];
00084         uint16_t n = size - 5;
00085         uint16_t c = 0;
00086 
00087         while (n > 1) {
00088                 c+= (*(buffer)<<8) | *(buffer+1);
00089                 n -= 2;
00090                 buffer += 2;
00091         }
00092         if (n > 0) c = c ^ (uint16_t)*buffer;
00093 
00094         return(c);
00095 }
00096 
00097 // You can supply a timeout in milliseconds
00098 int ErraticPacket::Receive( int fd, uint16_t wait ) {
00099         uint8_t prefix[3];
00100         uint32_t skipped;
00101         uint16_t cnt;
00102 
00103         if (debug_mode)
00104                 printf("Check for packets in Receive()\n");
00105 
00106         memset(packet,0,sizeof(packet));
00107         struct pollfd readpoll;
00108         readpoll.fd = fd; 
00109         readpoll.events = POLLIN | POLLPRI;
00110         readpoll.revents = 0;
00111         
00112 #ifdef USE_SELECT
00113         fd_set read_set, error_set;
00114         struct timeval tv;
00115         FD_ZERO(&read_set); 
00116         FD_ZERO(&error_set);
00117         FD_SET(fd, &read_set); 
00118         FD_SET(fd, &error_set);
00119         tv.tv_sec = 0;
00120         tv.tv_usec = 0;
00121         if (wait >= 1000)
00122                 tv.tv_sec = wait/1000;
00123         else
00124                 tv.tv_usec = wait*1000;
00125 #endif
00126 
00127         // This block will terminate or move on when there is data to read
00128         if (wait) {
00129                 while (1) {
00130 #ifdef USE_SELECT
00131                         int ret = select(fd+1, &read_set, 0, &error_set, &tv);
00132                         if (ret)
00133                                 {
00134                                         if (debug_mode)
00135                                                 printf("Data waiting\n");
00136                                         break;
00137                                 }
00138                         else
00139                                 if (debug_mode)
00140                                         printf("No data\n");
00141 #endif
00142 
00143                         int8_t stuff = poll(&readpoll, 1, wait);
00144                         
00145                         if (stuff < 0) {
00146                                 if (errno == EINTR) {
00147                                         continue;
00148                                 }
00149                                 return 1;
00150                         }
00151                         
00152                         if (stuff == 0) {
00153                                 return (receive_result_e)timeout;
00154                         }
00155 
00156                         if (readpoll.revents & POLLIN)
00157                                 break;
00158                         
00159                         printf("Serial port error\n");
00160                         return (receive_result_e)failure;
00161                 }
00162         }
00163         
00164         do {
00165                 memset(prefix,0,sizeof(prefix));
00166                 
00167                 skipped = 0;
00168                 while(1) {
00169                         cnt = 0;
00170                         
00171                         // Once we've started receiving a packet, we have a tight timeout
00172                         // Trouble with FTDI USB interface: needs longer timeout
00173                         while( cnt!=1 ) {
00174                                 if (wait) {
00175                                         while (1) {
00176 
00177 #ifdef USE_SELECT                                               
00178                                                 FD_ZERO(&read_set); 
00179                                                 FD_ZERO(&error_set);
00180                                                 FD_SET(fd, &read_set); 
00181                                                 FD_SET(fd, &error_set);
00182                                                 tv.tv_sec = 0;
00183                                                 tv.tv_usec = 100*1000; // in usec's
00184 
00185                                                 int ret = select(fd+1, &read_set, 0, &error_set, &tv);
00186                                                 if (ret)
00187                                                         break;
00188 #endif
00189 
00190                                                 int8_t stuff = poll(&readpoll, 1, 100);
00191 
00192                                                 if (stuff < 0) {
00193                                                         if (errno == EINTR) {
00194                                                                 continue;
00195                                                         }
00196                                                         return 1;
00197                                                 }
00198 
00199                                                 if (stuff == 0) {
00200                                                         return (receive_result_e)timeout;
00201                                                 }
00202 
00203                                                 if (readpoll.revents & POLLIN)
00204                                                         break;
00205 
00206                                                 printf("Serial port error\n");
00207                                                 return (receive_result_e)failure;
00208                                         }
00209                                 }
00210                                 
00211                                 
00212                                 int newcnt = read( fd, &prefix[2], 1 );
00213                                 if (debug_mode)
00214                                         printf("Read %d byte: %02x\n", newcnt, prefix[2]);
00215 
00216                                 if (newcnt < 0 && errno == EAGAIN)
00217                                         continue;
00218                                 else if (newcnt < 0) {
00219                                         perror("Erratic::Receive:read:");
00220                                         return(1);
00221                                 }
00222 
00223                                 cnt++;
00224                         }
00225 
00226                         if (prefix[0]==0xFA && prefix[1]==0xFB) break;
00227 
00228                         prefix[0]=prefix[1];
00229                         prefix[1]=prefix[2];
00230                         skipped++;
00231                         
00232                         if (skipped > 200) return (receive_result_e)timeout;
00233                 }
00234                 if (skipped>2 && debug_mode) printf("Skipped %d bytes\n", skipped);
00235 
00236                 size = prefix[2]+3;
00237                 memcpy( packet, prefix, 3);
00238 
00239                 cnt = 0;
00240                 while( cnt!=prefix[2] ) 
00241                 {
00242                         if (wait) {
00243                                 while (1) {
00244 #ifdef USE_SELECT
00245                                         FD_ZERO(&read_set); 
00246                                         FD_ZERO(&error_set);
00247                                         FD_SET(fd, &read_set); 
00248                                         FD_SET(fd, &error_set);
00249                                         tv.tv_sec = 0;
00250                                         tv.tv_usec = 100*1000;                          // in usec's
00251 
00252                                         int ret = select(fd+1, &read_set, 0, &error_set, &tv);
00253                                         if (ret)
00254                                                 break;
00255 #endif
00256 
00257                                         int8_t stuff = poll(&readpoll, 1, 100);
00258 
00259                                         if (stuff < 0) {
00260                                                 if (errno == EINTR) {
00261                                                         continue;
00262                                                 }
00263                                                 return 1;
00264                                         }
00265 
00266                                         if (stuff == 0) {
00267                                                 return (receive_result_e)timeout;
00268                                         }
00269 
00270                                         if (readpoll.revents & POLLIN)
00271                                                 break;
00272 
00273                                         printf("Serial port error\n");
00274                                         return (receive_result_e)failure;
00275                                 }
00276                         }
00277                         
00278                         int newcnt = read( fd, &packet[3+cnt], prefix[2]-cnt );
00279                         if (debug_mode)
00280                                 {
00281                                         printf("Read %d bytes packet\n", newcnt);
00282                                         if (newcnt > 0)
00283                                                 {
00284                                                         for (int i=0; i<newcnt; i++)
00285                                                                 printf("%02x ", packet[3+i]);
00286                                                         printf("\n");
00287                                                 }
00288                                 }
00289 
00290                         if (newcnt < 0 && errno == EAGAIN)
00291                                 continue;
00292                         else if (newcnt < 0) {
00293                                 perror("Erratic::Receive:read:");
00294                                 return(1);
00295                         }
00296 
00297                         cnt += newcnt;
00298                 }
00299         } while (!Check());  
00300         return(0);
00301 }
00302 
00303 
00304 int ErraticPacket::Build( unsigned char *data, unsigned char datasize ) {
00305         uint16_t chksum;
00306 
00307         size = datasize + 5;
00308 
00309         /* header */
00310         packet[0]=0xFA;
00311         packet[1]=0xFB;
00312 
00313         if ( size > 198 ) {
00314                 printf("Erratic driver error: Packet to robot can't be larger than 200 bytes");
00315                 return(1);
00316         }
00317         packet[2] = datasize + 2;
00318 
00319         memcpy( &packet[3], data, datasize );
00320 
00321         chksum = CalcChkSum();
00322         //if (chksum < 0) chksum += 0x8000;
00323         packet[3+datasize] = chksum >> 8;
00324         packet[3+datasize+1] = chksum;// & 0xFF;
00325 
00326         /*if (debug_mode) {
00327                 int16_t last = packet[3+datasize+1];
00328                 int32_t test = (packet[3+datasize] << 8) | last;
00329                 
00330                 printf("chksum that will be sent:%i , received: %i\n", chksum, test);
00331         }*/
00332         
00333         return(0);
00334 }
00335 
00336 int ErraticPacket::Send( int fd) {
00337         int cnt=0;
00338 
00339         //printf("Send(): ");
00340         //if (packet[3] != 0x0b && packet[3] != 0x15)
00341         //  PrintHex();
00342 
00343         //if (debug_mode)
00344         //      Print();
00345 
00346 
00347         while(cnt!=size)
00348         {
00349                 if((cnt += write( fd, packet+cnt, size-cnt )) < 0) 
00350                 {
00351                         perror("Send");
00352                         return(1);
00353                 }
00354         }
00355         return(0);
00356 }

Last updated 12 September 2005 21:38:45