00001 #include "khepera_serial.h"
00002
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/time.h>
00006 #include <fcntl.h>
00007 #include <termios.h>
00008 #include <stdio.h>
00009 #include <strings.h>
00010 #include <unistd.h>
00011 #include <stdlib.h>
00012 #include <errno.h>
00013 #include <string.h>
00014
00015
00016 KheperaSerial::KheperaSerial(char * port, int rate)
00017 {
00018 fd = -1;
00019
00020 pthread_mutex_init(&lock,NULL);
00021
00022
00023 fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
00024 if ( fd<0 )
00025 {
00026 fprintf(stderr, "Could not open serial device %s\n",port);
00027 return;
00028 }
00029
00030
00031
00032 tcgetattr(fd, &oldtio);
00033
00034
00035
00036
00037
00038 struct termios newtio;
00039 memset(&newtio, 0,sizeof(newtio));
00040 newtio.c_cflag = CS8 | CLOCAL | CREAD;
00041 newtio.c_iflag = IGNPAR;
00042 newtio.c_oflag = 0;
00043 newtio.c_lflag = ICANON;
00044
00045
00046 tcflush(fd, TCIFLUSH);
00047 if (cfsetispeed(&newtio, rate) < 0 || cfsetospeed(&newtio, rate) < 0)
00048 {
00049 fprintf(stderr,"Failed to set serial baud rate: %d\n", rate);
00050 tcsetattr(fd, TCSANOW, &oldtio);
00051 close(fd);
00052 fd = -1;
00053 return;
00054 }
00055 tcsetattr(fd, TCSANOW, &newtio);
00056 tcflush(fd, TCIOFLUSH);
00057
00058
00059 usleep(100000);
00060 write(fd,"\r\n",2);
00061 usleep(100000);
00062 tcflush(fd, TCIFLUSH);
00063
00064
00065 int Values[2];
00066 if (KheperaCommand('E',0,NULL,2,Values) < 0)
00067 {
00068 fprintf(stderr,"Failed to initialise the Khepera Serial Port %s\n",port);
00069 close(fd);
00070 fd = -1;
00071 }
00072 }
00073
00074
00075 KheperaSerial::~KheperaSerial()
00076 {
00077
00078 if (fd > 0)
00079 {
00080 tcsetattr(fd, TCSANOW, &oldtio);
00081 close(fd);
00082 }
00083 }
00084
00085 void KheperaSerial::Lock()
00086 {
00087 pthread_mutex_lock(&lock);
00088 }
00089
00090 void KheperaSerial::Unlock()
00091 {
00092 pthread_mutex_unlock(&lock);
00093 }
00094
00095 int KheperaSerial::WriteInts(char command, int Count, int * Values)
00096 {
00097
00098 if (fd < 0)
00099 return -1;
00100
00101 buffer[0] = command;
00102 buffer[1] = '\0';
00103 int length;
00104 for (int i = 0; i < Count; ++ i)
00105 {
00106 length = strlen(buffer);
00107 snprintf(&buffer[length],KHEPERA_BUFFER_LEN - length - 2,",%d",Values[i]);
00108 }
00109 length = strlen(buffer);
00110 snprintf(&buffer[length],KHEPERA_BUFFER_LEN - length ,"\n");
00111 length = strlen(buffer);
00112
00113
00114 tcflush(fd, TCIFLUSH);
00115 if(write(fd, buffer, length) < length)
00116 {
00117 fprintf(stderr,"Error writing to Khepera, disabling\n");
00118 tcsetattr(fd, TCSANOW, &oldtio);
00119 fd = -1;
00120 return -1;
00121 }
00122 return 0;
00123 }
00124
00125
00126
00127 int KheperaSerial::ReadInts(char Header, int Count, int * Values)
00128 {
00129 if (fd < 0)
00130 return -1;
00131 struct timeval Start,Now;
00132 int TimePassed = 0;
00133 gettimeofday(&Start,NULL);
00134 int length = 0;
00135 do
00136 {
00137 pthread_testcancel();
00138 length += read(fd, &buffer[length], KHEPERA_BUFFER_LEN - length);
00139 gettimeofday(&Now,NULL);
00140 TimePassed = (Now.tv_sec - Start.tv_sec)*1000000 + Now.tv_usec - Start.tv_usec;
00141 } while (buffer[length-1] != '\n' && TimePassed < KHEPERA_SERIAL_TIMEOUT_USECS);
00142
00143 if (TimePassed >= KHEPERA_SERIAL_TIMEOUT_USECS)
00144 {
00145 fprintf(stderr,"Time out while reading khepera reply\n");
00146 return -1;
00147 }
00148
00149 if (buffer[0] != Header)
00150 return -1;
00151
00152 char * pos = &buffer[2];
00153 for (int i = 0; i < Count; ++i)
00154 {
00155 Values[i] = strtol(pos,&pos,10);
00156 pos++;
00157 }
00158 return 0;
00159 }
00160
00161 int KheperaSerial::KheperaCommand(char command, int InCount, int * InValues, int OutCount, int * OutValues)
00162 {
00163
00164 Lock();
00165 int ret1 = WriteInts(command,InCount,InValues);
00166 usleep(10000);
00167 int ret2 = ReadInts(command + 32,OutCount,OutValues);
00168 Unlock();
00169 return ret1 < ret2 ? ret1 : ret2;
00170 }