rflex_driver.cc
Go to the documentation of this file.
00001 /*
00002  *  RFlex Driver
00003  *  David Lu!! - 2/2010
00004  *  Modified from Player driver
00005  *
00006  *  Player - One Hell of a Robot Server
00007  *  Copyright (C) 2000
00008  *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
00009  *
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00027 #include <rflex/rflex_driver.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <netinet/in.h>
00031 #include <termios.h>
00032 #include <sys/stat.h>
00033 #include <iostream>
00034 #include <unistd.h>
00035 #include <string.h> // memcpy
00036 #include <fcntl.h>
00037 
00038 //finds the sign of a value
00039 static long sgn( long val ) {
00040     if (val < 0)
00041         return 0;
00042     else
00043         return 1;
00044 }
00045 
00046 static unsigned int getInt16( const unsigned char *bytes ) {
00047     unsigned int i;
00048     memcpy( &i, bytes, 2 );
00049     return(htons(i));
00050 }
00051 
00052 
00053 static unsigned long getInt32( const unsigned char *bytes ) {
00054     unsigned long i;
00055     memcpy( &i, bytes, 4 );
00056     return(htonl(i));
00057 }
00058 
00059 
00060 static void putInt8( unsigned int i, unsigned char *bytes ) {
00061     memcpy( bytes, &i, 1 );
00062 }
00063 
00064 static void putInt32( unsigned long l, unsigned char *bytes ) {
00065     uint32_t conv;
00066     conv = htonl( l );
00067     memcpy( bytes, &conv, 4 );
00068 }
00069 
00070 RFLEX::RFLEX() {
00071     distance = bearing = transVelocity = rotVelocity = 0;
00072     voltage = 0;
00073     offset = 0;
00074     odomReady = 0;
00075     found = false;
00076     brake = true;
00077 
00078     // initialise the LCD dump array
00079     lcdData=new unsigned char[320*240/8];
00080     if (lcdData != NULL) {
00081         lcdX=320/8;
00082         lcdY=240;
00083     }
00084 }
00085 
00086 int RFLEX::initialize(const char* device_name) {
00087     // Open the port
00088     fd = open(device_name, O_RDWR | O_NONBLOCK);
00089     if (fd == -1) {
00090         fprintf(stderr,"Could not open serial port %s\n", device_name );
00091         return -1;
00092     }
00093 
00094     // Get the terminal info
00095     struct termios info;
00096     if (tcgetattr(fd, &info) < 0) {
00097         fprintf(stderr,"Could not get terminal information for %s\n", device_name );
00098         return -1;
00099     }
00100 
00101     // Turn off echo, canonical mode, extended processing, signals, break signal, cr to newline, parity off, 8 bit strip, flow control,
00102     // size, parity bit, and output processing
00103     info.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | BRKINT | ICRNL | INPCK | ISTRIP | IXON | CSIZE | PARENB | OPOST);
00104 
00105     // Set size to 8 bits
00106     info.c_cflag |= CS8;
00107 
00108     // Set time and bytes to enable read at once
00109     info.c_cc[VTIME] = 0;
00110     info.c_cc[VMIN] = 0;
00111     speed_t baud_rate = B115200;
00112     if (cfsetospeed(&info, baud_rate) < 0) {
00113         fprintf(stderr,"Could not set the output speed for %s\n", device_name );
00114         return -1;
00115     }
00116 
00117     if (cfsetispeed(&info, baud_rate) < 0) {
00118         fprintf(stderr,"Could not set the input speed for %s\n", device_name );
00119         return -1;
00120     }
00121 
00122     // Actually set the controls on the terminal
00123     if (tcsetattr(fd, TCSAFLUSH, &info) < 0) {
00124         close(fd);
00125         fprintf(stderr,"Could not set controls on serial port %s\n", device_name );
00126     }
00127 
00128     pthread_mutex_init(&writeMutex, NULL);
00129     pthread_create(&thread, NULL, RFLEX::readThread, this);
00130 
00131     return 0;
00132 }
00133 
00134 RFLEX::~RFLEX() {
00135     // empty destructor
00136 }
00137 
00138 void RFLEX::configureSonar(const unsigned long echo_delay, const unsigned long ping_delay,
00139                            const unsigned long set_delay, const unsigned long val) {
00140 
00141     unsigned char data[MAX_COMMAND_LENGTH];
00142     putInt32( echo_delay, &(data[0]) );
00143     putInt32( ping_delay, &(data[4]) );
00144     putInt32( set_delay , &(data[8]) );
00145     putInt8(  val, &(data[12]) );
00146     sendCommand(SONAR_PORT, 4, SONAR_RUN, 13, data );
00147 }
00148 
00149 void RFLEX::setIrPower( const bool on ) {
00150     unsigned char data[MAX_COMMAND_LENGTH];
00151     long v1, v2, v3, v4, v5;
00152     unsigned char v6;
00153     if (on) {
00154         v1 = 0;
00155         v2 = 70;
00156         v3 = 10;
00157         v4 = 20;
00158         v5 = 150;
00159         v6 = 2;
00160     } else {
00161         v1 = v2 = v3 = v4 = v5 = 0;
00162         v6 = 0;
00163     }
00164 
00165     putInt32( v1, &(data[0]) );
00166     putInt32( v2, &(data[4]) );
00167     putInt32( v3, &(data[8]) );
00168     putInt32( v4, &(data[12]) );
00169     putInt32( v5, &(data[16]) );
00170     putInt8(  v6, &(data[20]) );
00171     sendCommand(IR_PORT, 0, IR_RUN, 21, data );
00172 }
00173 
00174 void RFLEX::setBrakePower( const bool on ) {
00175     int brake;
00176     if (on)
00177         brake = MOT_BRAKE_SET;
00178     else
00179         brake = MOT_BRAKE_RELEASE;
00180 
00181     sendCommand(MOT_PORT, 0, brake, 0, NULL );
00182 }
00183 
00184 void RFLEX::motionSetDefaults(  ) {
00185     sendCommand(MOT_PORT, 0, MOT_SET_DEFAULTS, 0, NULL );
00186 }
00187 
00188 void RFLEX::setDigitalIoPeriod( const long period ) {
00189     unsigned char data[MAX_COMMAND_LENGTH];
00190     putInt32( period, &(data[0]) );
00191     sendCommand(DIO_PORT, 0, DIO_REPORTS_REQ, 4, data );
00192 }
00193 
00194 void RFLEX::setOdometryPeriod( const long period ) {
00195     unsigned char data[MAX_COMMAND_LENGTH];
00196     long mask;
00197     if (period==0)
00198         mask = 0;
00199     else
00200         mask = 3;
00201 
00202     putInt32( period, &(data[0]) );         /* period in ms */
00203     putInt32( mask, &(data[4]) );           /* mask */
00204     sendCommand(MOT_PORT, 0, MOT_SYSTEM_REPORT_REQ, 8, data );
00205 }
00206 
00207 void RFLEX::setVelocity( const long tvel, const long rvel, const long acceleration) {
00208     long utvel =labs(tvel);
00209     long urvel =labs(rvel);
00210     unsigned char data[MAX_COMMAND_LENGTH];
00211     // ** workaround for stupid hardware bug, cause unknown, but this works
00212     // ** with minimal detriment to control
00213     // ** avoids all values with 1b in highest or 3'rd highest order byte
00214     
00215     // 0x1b is part of the packet terminating string
00216     // which is most likely what causes the bug
00217 
00218     // ** if 2'nd order byte is 1b, round to nearest 1c, or 1a
00219     if((urvel&0xff00)==0x1b00){
00220       // ** if lowest order byte is>127 round up, otherwise round down
00221       urvel=(urvel&0xffff0000)|((urvel&0xff)>127?0x1c00:0x1aff);
00222     }
00223 
00224     // ** if highest order byte is 1b, round to 1c, otherwise round to 1a
00225     if((urvel&0xff000000)==0x1b000000){
00226       // ** if 3'rd order byte is>127 round to 1c, otherwise round to 1a
00227       urvel=(urvel&0x00ffffff)|(((urvel&0xff0000)>>16)>127?0x1c000000:0x1aff0000);
00228     }
00229 
00230 
00231     putInt8( 0,                 &(data[0]) );       /* forward motion */
00232     putInt32( utvel,            &(data[1]) );       /* abs trans velocity*/
00233     putInt32( acceleration,     &(data[5]) );       /* trans acc */
00234     putInt32( STD_TRANS_TORQUE, &(data[9]) );       /* trans torque */
00235     putInt8( sgn(tvel),         &(data[13]) );      /* trans direction */
00236 
00237     sendCommand(MOT_PORT, 0, MOT_AXIS_SET_DIR, 14, data );
00238 
00239     putInt8( 1,                 &(data[0]) );       /* rotational motion */
00240     putInt32( urvel,            &(data[1]) );       /* abs rot velocity  */
00241     /* 0.275 rad/sec * 10000 */
00242     putInt32( STD_ROT_ACC,      &(data[5]) );       /* rot acc */
00243     putInt32( STD_ROT_TORQUE,   &(data[9]) );       /* rot torque */
00244     putInt8( sgn(rvel),         &(data[13]) );      /* rot direction */
00245 
00246     sendCommand(MOT_PORT, 0, MOT_AXIS_SET_DIR, 14, data );
00247 }
00248 
00249 void RFLEX::sendSystemStatusCommand() {
00250     sendCommand(SYS_PORT, 0, SYS_STATUS, 0, NULL );
00251 }
00252 
00253 void RFLEX::parseMotReport( const unsigned char* buffer ) {
00254     int rv, timeStamp, acc, trq;
00255     unsigned char axis;
00256 
00257     switch (buffer[PACKET_OPCODE_BYTE]) {
00258     case MOT_SYSTEM_REPORT:
00259         rv        = getInt32(&(buffer[6]));
00260         timeStamp = getInt32(&(buffer[10]));
00261         axis      = buffer[14];
00262         if (axis == 0) {
00263             distance = getInt32(&(buffer[15]));
00264             transVelocity = getInt32(&(buffer[19]));
00265             odomReady = odomReady | 1;
00266         } else if (axis == 1) {
00267             bearing = getInt32(&(buffer[15]));
00268             rotVelocity = getInt32(&(buffer[19]));
00269             odomReady = odomReady | 2;
00270         }
00271         acc       = getInt32(&(buffer[23]));
00272         trq       = getInt32(&(buffer[27]));
00273         break;
00274     default:
00275         break;
00276     }
00277 }
00278 
00279 //processes a digital io packet from the rflex
00280 void RFLEX::parseDioReport( const unsigned char* buffer ) {
00281     unsigned long timeStamp;
00282     unsigned char length, address;
00283     unsigned short data;
00284     length = buffer[5];
00285 
00286     switch (buffer[PACKET_OPCODE_BYTE]) {
00287     case DIO_REPORT:
00288         if (length < 6) {
00289             fprintf(stderr, "DIO Data Packet too small\n");
00290             break;
00291         }
00292         timeStamp = getInt32(&(buffer[6]));
00293         address = buffer[10];
00294         data = getInt16(&(buffer[11]));
00295         processDioEvent(address, data);
00296 
00297         break;
00298     default:
00299         break;
00300     }
00301 }
00302 
00303 void RFLEX::processDioEvent(unsigned char address, unsigned short data) {
00304     printf("DIO: address 0x%02x (%d) value 0x%02x (%d)\n", address, address, data, data);
00305 }
00306 
00307 // Processes the IR sensor report
00308 void RFLEX::parseIrReport( const unsigned char* buffer ) {
00309     /*
00310     unsigned char length = buffer[5];
00311 
00312     // allocate ir storage if we havent already
00313     // must be a better place to do this but it works
00314     if (numIr== 0 && IR_POSES_COUNT > 0) {
00315         irRanges = new unsigned char[IR_POSES_COUNT];
00316         if (irRanges != NULL)
00317             numIr = IR_POSES_COUNT;
00318         else
00319             fprintf(stderr,"Error allocating ir range storage in rflex status\n");
00320     }
00321 
00322     switch (buffer[PACKET_OPCODE_BYTE]) {
00323     case IR_REPORT: {
00324         if (length < 1) {
00325             fprintf(stderr, "IR Data Packet too small\n");
00326             break;
00327         }
00328 
00329         // get number of IR readings to make
00330         unsigned char pckt_ir_count = buffer[6];
00331         if (pckt_ir_count < IR_BASE_BANK)
00332             pckt_ir_count = 0;
00333         else
00334             pckt_ir_count -= IR_BASE_BANK;
00335 
00336         if (pckt_ir_count > IR_BANK_COUNT)
00337             pckt_ir_count = IR_BANK_COUNT;
00338 
00339 
00340         // now actually read the ir data
00341         int ir_data_index = 0;
00342         for (int i=0; i < IR_BANK_COUNT && ir_data_index < numIr; ++i) {
00343             for (int j = 0; j < IR_PER_BANK && ir_data_index < numIr; ++j,++ir_data_index) {
00344                 // work out the actual offset in teh packet
00345                 //(current bank + bank offfset) * bank data block size + current ir sensor + constant offset
00346                 int data_index = (IR_BASE_BANK + i) * 13 + j + 11;
00347                 irRanges[ir_data_index] = buffer[data_index];
00348             }
00349         }
00350 
00351         break;
00352     }
00353     default:
00354         break;
00355     }*/
00356 #warning IR Unreported
00357 
00358 }
00359 
00360 
00361 //processes a sys packet from the rflex - and saves the data in the
00362 //struct for later use, sys is primarily used for bat voltage & brake status
00363 void RFLEX::parseSysReport( const unsigned char* buffer ) {
00364     unsigned long timeStamp;
00365     unsigned char length = buffer[5];
00366 
00367 
00368     switch (buffer[PACKET_OPCODE_BYTE]) {
00369     case SYS_LCD_DUMP:
00370         // currently designed for 320x240 screen on b21r
00371         // stored in packed format
00372         if (length < 6) {
00373             fprintf(stderr, "Got bad Sys packet (lcd)\n");
00374             break;
00375         }
00376 
00377         unsigned char lcd_length, row;
00378         timeStamp=getInt32(&(buffer[6]));
00379         row = buffer[10];
00380         lcd_length = buffer[11];
00381         if (row > lcdY || lcd_length > lcdX) {
00382             fprintf(stderr,"LCD Data Overflow\n");
00383             break;
00384         }
00385 
00386         memcpy(&lcdData[row*lcdX],&buffer[12],lcd_length);
00387 
00388         // if we got whole lcd dump to file
00389         /*                      if (row == 239){
00390                                         FILE * fout;
00391                                         if ((fout = fopen("test.raw","w"))!=0){
00392                                                 for (int y=0; y<lcdY; ++y){
00393                                                         for (int x=0; x<lcdX;++x){
00394                                                                 unsigned char Temp = lcdData[y*lcdX + x];
00395                                                                 for (int i = 0; i < 8; ++i){
00396                                                                         if ((Temp >> i) & 0x01)
00397                                                                                 fprintf(fout,"%c",0x0);
00398                                                                         else
00399                                                                                 fprintf(fout,"%c",0xFF);
00400                                                                 }
00401                                                         }
00402                                                         fprintf(fout,"\n");
00403                                                 }
00404                                         }
00405                                         fclose(fout);
00406                                 }*/
00407 
00408 
00409         break;
00410 
00411     case SYS_STATUS:
00412         if (length < 9) {
00413             fprintf(stderr, "Got bad Sys packet (status)\n");
00414             break;
00415         }
00416         timeStamp=getInt32(&(buffer[6]));
00417         // raw voltage measurement...needs calibration offset added
00418         voltage=getInt32(&(buffer[10]));
00419         brake=buffer[14];
00420 
00421         break;
00422 
00423     default:
00424         fprintf(stderr,"Unknown sys opcode recieved\n");
00425     }
00426 }
00427 
00428 //processes a sonar packet from the rflex
00429 void RFLEX::parseSonarReport( const unsigned char* buffer ) {
00430     int retval, timeStamp, count;
00431     unsigned char dlen = buffer[5];
00432 
00433     switch (buffer[PACKET_OPCODE_BYTE]) {
00434     case SONAR_REPORT:
00435         retval    = getInt32(&(buffer[6]));
00436         timeStamp = getInt32(&(buffer[10]));
00437         count = 0;
00438         while ((8+count*3<dlen) && (count<256) && (count < SONAR_MAX_COUNT)) {
00439             unsigned int sid = buffer[14+count*3];
00440             sonar_ranges[sid] = getInt16( &(buffer[14+count*3+1]) );
00441             count++;
00442         }
00443         break;
00444     default:
00445         break;
00446     }
00447 }
00448 
00449 //processes a joystick packet from the rflex, and sets as command if
00450 // joystick command enabled
00451 void RFLEX::parseJoyReport( const unsigned char* buffer ) {
00452     /*unsigned char* buffer = buffer->data();
00453 
00454     static bool JoystickWasOn = false;
00455 
00456     int x,y;
00457     unsigned char buttons, dlen = buffer[5];
00458 
00459     switch (buffer[PACKET_OPCODE_BYTE]) {
00460     case JSTK_GET_STATE:
00461         if (dlen < 13) {
00462             fprintf(stderr,"Joystick Packet too small\n");
00463             break;
00464         }
00465         x = getInt32(&buffer[10]);
00466         y = getInt32(&buffer[14]);
00467         buttons = buffer[18];
00468 
00469         if ((buttons & 1) == 1) {
00470             JoystickWasOn = true;
00471             setVelocity((long) (y * JOY_POS_RATIO * ODO_DISTANCE_CONVERSION),
00472                          (long) (x * JOY_ANG_RATIO * ODO_ANGLE_CONVERSION),
00473                          (long) (DEFAULT_TRANS_ACCELERATION * ODO_DISTANCE_CONVERSION));
00474             //RFLEX::joy_control = 5;
00475         } else if (JoystickWasOn) {
00476             JoystickWasOn = false;
00477             setVelocity(0,0,(long) (DEFAULT_TRANS_ACCELERATION * ODO_DISTANCE_CONVERSION));
00478             //RFLEX::joy_control = 5;
00479         }
00480 
00481         break;
00482     default:
00483         break;
00484     }*/
00485 #warning joystick control not implemented
00486 
00487 }
00488 
00489 
00490 //parses a packet from the rflex, and decides what to do with it
00491 void RFLEX::parsePacket( const unsigned char* buffer ) {
00492     switch (buffer[PACKET_PORT_BYTE]) {
00493     case SYS_PORT:
00494         parseSysReport( buffer );
00495         break;
00496     case MOT_PORT:
00497         parseMotReport( buffer );
00498         break;
00499     case JSTK_PORT:
00500         parseJoyReport( buffer );
00501         break;
00502     case SONAR_PORT:
00503         parseSonarReport( buffer );
00504         break;
00505     case DIO_PORT:
00506         parseDioReport( buffer );
00507         break;
00508     case IR_PORT:
00509         parseIrReport( buffer);
00510         break;
00511     default:
00512         break;
00513     }
00514 }
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 void* RFLEX::readThread(void *ptr) {
00523     RFLEX *rflex = static_cast<RFLEX *>(ptr);
00524 
00525     while (rflex->fd>=0) {
00526         // Set up the read set to include the serial port
00527         fd_set read_set;
00528         FD_ZERO(&read_set);
00529         FD_SET(rflex->fd, &read_set);
00530 
00531         // Is there any new data to be read from the rFlex?
00532         if (select(rflex->fd + 1, &read_set, NULL, NULL, NULL) < 0) {
00533             //debug("Error in select\n");
00534         } else if (FD_ISSET(rflex->fd, &read_set)) {
00535             rflex->readPacket();
00536         }
00537     }
00538     return NULL;
00539 }
00540 
00541 
00542 void RFLEX::readPacket() {
00543     // If there's no packet ready, just return
00544     const int read_size = readData();
00545     if (read_size == 0)
00546         return;
00547 
00548     // Check to make sure that the packet is the correct size
00549     const int data_size = read_size - PROTOCOL_SIZE;
00550     if (readBuffer[PACKET_SIZE_BYTE] != data_size) {
00551         //debug("Error in packet size.  Expected %i, got %i\n", data_size, static_cast<int>(readBuffer[PACKET_SIZE_BYTE]));
00552         for (int i = 0; i < BUFFER_SIZE; ++i) {
00553             //                  debug("%2x ", static_cast<int>(readBuffer[i]));
00554             //                  if (((i + 1) % 10) == 0)
00555             //                          debug("\n");
00556         }
00557     }
00558 
00559     // Calculate the packet CRC and verify that it matches
00560     if (computeCRC(readBuffer + PACKET_CRC_START, data_size + PACKET_CRC_OFFSET) != readBuffer[data_size + PACKET_DATA_START_BYTE]) {
00561         //              debug("CRC error: Expected %i, got %i\n", static_cast<int>(readBuffer[read_size - PROTOCOL_SIZE + PACKET_DATA_START_BYTE]), static_cast<int>(computeCRC(readBuffer + PACKET_CRC_START, data_size + PACKET_CRC_OFFSET)));
00562 
00563         for (int i = 0; i < BUFFER_SIZE; ++i) {
00564             //                  debug("%2x ", static_cast<int>(readBuffer[i]));
00565             //  if (((i + 1) % 10) == 0)
00566             //  debug("\n");
00567         }
00568 
00569         // Eat everything up to the end of the packet
00570         unsigned char tdata = 0;
00571         while (tdata != ETX)
00572             while (read(fd, &tdata, 1) != 1) { }
00573 
00574         return;
00575     }
00576 
00577     parsePacket(readBuffer);
00578 }
00579 
00580 
00581 int RFLEX::readData() {
00582     // Read one byte of of the packet.  No need to check for errors, since this will be called repeatedly.
00583 
00584     int bRead = read(fd, readBuffer + offset, 1);
00585     if (bRead == 0)
00586         return 0;
00587     else if (bRead < 0) {
00588         printf("Error reading from port!\n");
00589         return 0;
00590     }
00591 
00592 
00593     // Have we started a packet yet?
00594     if (!found) {
00595         // If the first character isn't an ESC, the packet is invalid.  Reset the offset and return.  This
00596         // will eat badly-formed packets.
00597         if (readBuffer[0] != ESC) {
00598             offset = 0;
00599             return 0;
00600         }
00601         if (offset == 0) {
00602             offset = 1;
00603             return 0;
00604         }
00605 
00606         // We have to wait for a STX to show up before it's a valid packet.  If we see an ESC, then we just
00607         // keep looking for an STX.  If we see something else, give up and start looking for a new packet.
00608         if (readBuffer[1] == STX) {
00609             found = true;
00610             offset = 2;
00611             return 0;
00612         } else if (readBuffer[1] == ESC) {
00613             offset = 1;
00614             return 0;
00615         } else {
00616             offset = 0;
00617             return 0;
00618         }
00619     } else {
00620         // If the previous character was an ESC,
00621         if (readBuffer[offset - 1] == ESC) {
00622             switch (readBuffer[offset]) {
00623             case NUL:  // Skip over NULs
00624                 read(fd, readBuffer + offset, 1);  // Should we be checking the return code here?
00625                 ++offset;
00626                 return 0;
00627             case SOH:  // Ignore SOHs by deleting them
00628                 --offset;
00629                 return 0;
00630             case ETX: // ETX ends the packet, so return the length
00631                 const int retval = offset + 1;
00632                 found = false;
00633                 offset = 0;
00634                 return retval;
00635             };
00636         } else {
00637             // Just increment the counter
00638             ++offset;
00639 
00640             return 0;
00641         }
00642     }
00643 
00644     // Should never get here
00645     return 0;
00646 }
00647 
00648 
00649 bool RFLEX::sendCommand(const unsigned char port, const unsigned char id, const unsigned char opcode, const int length, unsigned char* data) {
00650     pthread_mutex_lock(&writeMutex);
00651 
00652     // Header
00653     writeBuffer[0] = ESC;
00654     writeBuffer[1] = STX;
00655     writeBuffer[PACKET_PORT_BYTE] = port;
00656     writeBuffer[PACKET_ID_BYTE] = id;
00657     writeBuffer[PACKET_OPCODE_BYTE] = opcode;
00658     writeBuffer[PACKET_SIZE_BYTE] = static_cast<unsigned char>(length);
00659     for (int i=0; i<length; i++) {
00660         writeBuffer[6+i] = data[i];
00661     }
00662     // Footer
00663     writeBuffer[length + PACKET_DATA_START_BYTE] = computeCRC(writeBuffer + PACKET_CRC_START, length + PACKET_CRC_OFFSET);
00664     writeBuffer[length + PACKET_DATA_START_BYTE + 1] = ESC;
00665     writeBuffer[length + PACKET_DATA_START_BYTE + 2] = ETX;
00666 
00667     int ret = writePacket(length + 9);
00668     pthread_mutex_unlock(&writeMutex);
00669     return ret;
00670 }
00671 
00672 
00673 bool RFLEX::writePacket(const int length) const {
00674     if (fd<0)
00675         return false;
00676 
00677     int bytes_written = 0;
00678 
00679     while (bytes_written < length) {
00680         int n = write(fd, writeBuffer + bytes_written, length - bytes_written);
00681         if (n < 0)
00682             return false;
00683         else
00684             bytes_written += n;
00685 
00686         // Put in a short wait to let the rFlex controller catch up
00687         usleep(1000);
00688     }
00689 
00690     return true;
00691 }
00692 
00693 unsigned char RFLEX::computeCRC(const unsigned char *buffer, const int n) {
00694     int crc =buffer[0];
00695     for (int i = 1; i < n; ++i)
00696         crc ^= buffer[i];
00697     return crc;
00698 }
00699 


rflex
Author(s): David V. Lu!!, Mikhail Medvedev
autogenerated on Fri Aug 28 2015 12:58:58