Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArSickPacketReceiver.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArSickPacketReceiver.h"
00030 #include "ArLog.h"
00031 #include "ariaUtil.h"
00032 
00033 
00040 ArSickPacketReceiver::ArSickPacketReceiver(
00041         unsigned char receivingAddress, bool allocatePackets,
00042         bool useBase0Address) 
00043 {
00044   myAllocatePackets = allocatePackets;
00045   myReceivingAddress = receivingAddress;
00046   myDeviceConn = NULL;
00047   myUseBase0Address = useBase0Address;
00048 }
00049 
00057 ArSickPacketReceiver::ArSickPacketReceiver(
00058         ArDeviceConnection *deviceConnection, 
00059         unsigned char receivingAddress, bool allocatePackets,
00060         bool useBase0Address)
00061 {
00062   myDeviceConn = deviceConnection;
00063   myAllocatePackets = allocatePackets;
00064   myReceivingAddress = receivingAddress;
00065   myUseBase0Address = useBase0Address;
00066 }
00067 
00068 ArSickPacketReceiver::~ArSickPacketReceiver() 
00069 {
00070   
00071 }
00072 
00073 void ArSickPacketReceiver::setDeviceConnection(
00074         ArDeviceConnection *deviceConnection)
00075 {
00076   myDeviceConn = deviceConnection;
00077 }
00078 
00079 ArDeviceConnection *ArSickPacketReceiver::getDeviceConnection(void)
00080 {
00081   return myDeviceConn;
00082 }
00083 
00093 ArSickPacket *ArSickPacketReceiver::receivePacket(
00094         unsigned int msWait)
00095 {
00096   ArSickPacket *packet;
00097   unsigned char c;
00098   char buf[2048];
00099   long count = 0;
00100   // state can be one of the STATE_ enums in the class
00101   int state = STATE_START;
00102   //unsigned int timeDone;
00103   //unsigned int curTime;
00104   long timeToRunFor;
00105   long packetLength;
00106   ArTime timeDone;
00107   ArTime lastDataRead;
00108   ArTime packetReceived;
00109   int numRead;
00110 
00111 
00112   if (myDeviceConn == NULL || 
00113       myDeviceConn->getStatus() != ArDeviceConnection::STATUS_OPEN)
00114   {
00115     return NULL;
00116   }
00117   
00118   timeDone.setToNow();
00119   timeDone.addMSec(msWait);
00120   do
00121   {
00122     timeToRunFor = timeDone.mSecTo();
00123     if (timeToRunFor < 0)
00124       timeToRunFor = 0;
00125 
00126     if (myDeviceConn->read((char *)&c, 1, timeToRunFor) == 0) 
00127     {
00128       if (state == STATE_START)
00129       {
00130         return NULL;
00131       }
00132       else
00133       {
00134         //ArUtil::sleep(1);
00135         continue;
00136       }
00137     }
00138 
00139     //printf("%x\n", c);
00140     switch (state) {
00141     case STATE_START:
00142       if (c == 0x02) // move on, resetting packet
00143       {
00144         //printf("###############\n");
00145         state = STATE_ADDR;
00146         myPacket.empty();
00147         myPacket.setLength(0);
00148         myPacket.uByteToBuf(c);
00149         packetReceived = myDeviceConn->getTimeRead(0);
00150         myPacket.setTimeReceived(packetReceived);
00151       }
00152       /*else
00153       {
00154         //printf(" BAD\n");
00155         }*/
00156       break;
00157     case STATE_ADDR:
00158       // if this is correct move on, adding this byte... this is taken
00159       // out in favor of a more inclusive approach, if someone ever
00160       // wnats to drive multiple robots off of one serial port just
00161       // put this back in, or I don't know, punt
00162       //if (c == ((unsigned char)0x80 + myReceivingAddress)) 
00163       if (!myUseBase0Address && c >= 0x80 && c <= 0x84)
00164       {
00165         state = STATE_START_COUNT;
00166         myPacket.uByteToBuf(c);
00167       }
00168       // c will always be >= 0 since its unsigned
00169       else if (myUseBase0Address && c <= 0x4)
00170       {
00171         state = STATE_START_COUNT;
00172         myPacket.uByteToBuf(c);
00173       }
00174       else // go back to beginning, packet hosed
00175       {
00176         ArLog::log(ArLog::Terse, 
00177                    "ArSickPacketReceiver::receivePacket: wrong address (0x%x instead of 0x%x)", c, (unsigned) 0x80 + myReceivingAddress);
00178         state = STATE_START;
00179       }
00180       break;
00181     case STATE_START_COUNT:
00182       packetLength = c;
00183       myPacket.uByteToBuf(c);
00184       state = STATE_ACQUIRE_DATA;
00185       break;
00186     case STATE_ACQUIRE_DATA:
00187       // the character c is high ordre byte of the packet length count 
00188       // so we'll just build the length of the packet then get the 
00189       //rest of the data
00190       myPacket.uByteToBuf(c);
00191       packetLength = packetLength | (c << 8);
00192       count = 0;
00193       // make sure the length isn't longer than the maximum packet length...
00194       // getting some wierd 25k or 44k long packets (um, no)
00195       if (packetLength > ((long)myPacket.getMaxLength() -
00196                           (long)myPacket.getHeaderLength()))
00197       {
00198         ArLog::log(ArLog::Normal, 
00199            "ArSickPacketReceiver::receivePacket: packet too long, it is %d long while the maximum is %d.", packetLength, myPacket.getMaxLength());
00200         state = STATE_START;
00201         //myPacket.log();
00202         break;
00203       }
00204       // here we read until we get as much as we want, OR until
00205       // we go 100 ms without data... its arbitrary but it doesn't happen often
00206       // and it'll mean a bad packet anyways
00207       lastDataRead.setToNow();
00208       while (count < packetLength + 2)
00209       {
00210         numRead = myDeviceConn->read(buf + count, packetLength + 2- count, 1);
00211         if (numRead > 0)
00212           lastDataRead.setToNow();
00213         if (lastDataRead.mSecTo() < -100)
00214         {
00215           return NULL;
00216         }
00217         count += numRead;
00218       }
00219       myPacket.dataToBuf(buf, packetLength + 2);
00220       if (myPacket.verifyCRC()) 
00221       {
00222         myPacket.resetRead();
00223         //printf("Received ");
00224         //myPacket.log();
00225         if (myAllocatePackets)
00226         {
00227           packet = new ArSickPacket;
00228           packet->duplicatePacket(&myPacket);
00229           return packet;
00230         }
00231         else
00232           return &myPacket;
00233       }
00234       else 
00235       {
00236         ArLog::log(ArLog::Normal, 
00237            "ArSickPacketReceiver::receivePacket: bad packet, bad checksum");
00238         state = STATE_START;
00239         //myPacket.log();
00240         break;
00241       }
00242       break;
00243     default:
00244       break;
00245     }
00246   } while (timeDone.mSecTo() >= 0 || state != STATE_START);
00247 
00248   //printf("finished the loop...\n");
00249   return NULL;
00250 
00251 }
00252 
00253 

Generated on Wed Oct 19 12:56:37 2005 for Aria by  doxygen 1.4.0