/[H7]/branches/linux-serial/Serial.cpp
ViewVC logotype

Contents of /branches/linux-serial/Serial.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download)
Mon Feb 5 10:10:18 2007 UTC (17 years, 3 months ago) by torben
File size: 7579 byte(s)
Added a cross-platform specification of desired baud-rate.

1 #ifndef _MSC_VER //linux
2 #include <sys/types.h>
3 #include <sys/stat.h>
4
5 #include <unistd.h>
6 #include <errno.h>
7 #include <termios.h>
8 #include <fcntl.h>
9 #endif
10
11 #include "stdafx.h"
12 #include "Serial.h"
13
14 #include <stdexcept>
15 #include <string>
16 #include <sstream>
17 #include <iostream>
18 #include <iomanip>
19
20 #define _POSIX_SOURCE 1 /* POSIX compliant source */
21 #define BAUDRATE B9600
22
23 #ifndef _MSC_VER // ugly hack, else will gcc not accept this constant in openLinux()
24 const int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
25 #endif
26
27 std::string writeLastError()
28 {
29 #ifdef _MSC_VER
30 LPVOID lpMsgBuf;
31 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
32 NULL,
33 GetLastError(),
34 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
35 (LPSTR) &lpMsgBuf,
36 0,
37 NULL);
38
39 std::ostringstream out;
40 out << "Error" << lpMsgBuf;
41 return out.str();
42 #else //linux
43 return std::string( strerror(errno) );
44 #endif
45 }
46
47
48 CSerial::CSerial()
49 {
50 mIsopen = false;
51 }
52
53
54 CSerial::CSerial(char* port, Baudrate bitrate)
55 {
56 mPortstr = port;
57 mBitrate = bitrate;
58 mIsopen = false;
59
60 #ifdef _MSC_VER
61 openWindows();
62 #else
63 openLinux();
64 #endif
65 }
66
67 CSerial::~CSerial(void)
68 {
69 close();
70 }
71
72 void CSerial::open(char* port, Baudrate bitrate)
73 {
74 if (mIsopen)
75 throw std::runtime_error("Port already opened");
76
77 mPortstr = port;
78 mBitrate = bitrate;
79
80 #ifdef _MSC_VER
81 openWindows();
82 #else
83 openLinux();
84 #endif
85 }
86
87 #ifdef _MSC_VER
88 void CSerial::openWindows()
89 {
90 mComport = CreateFile( mPortstr, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
91
92 if (mComport == INVALID_HANDLE_VALUE)
93 {
94 throw std::runtime_error(writeLastError().c_str());
95 }
96
97 DCB dcb;
98 dcb.DCBlength = sizeof(DCB);
99 mDcbRestore.DCBlength = sizeof(DCB);
100
101 if (!GetCommState(mComport,&dcb) || !GetCommState(mComport,&mDcbRestore))
102 {
103 std::string error = writeLastError();
104 CloseHandle(mComport);
105 throw std::exception(error.c_str());
106 }
107
108 dcb.BaudRate = convertBaudrate(mBitrate);
109 dcb.ByteSize = 8;
110 dcb.Parity = NOPARITY;
111 dcb.StopBits = ONESTOPBIT;
112 dcb.fDtrControl = DTR_CONTROL_DISABLE;
113 dcb.fRtsControl = RTS_CONTROL_DISABLE;
114 dcb.fParity = false;
115 dcb.fDsrSensitivity = false;
116
117 if (!SetCommState(mComport,&dcb))
118 {
119 std::string error = writeLastError();
120 CloseHandle(mComport);
121 throw std::runtime_error( error );
122 }
123
124 mIsopen = true;
125 }
126 #endif
127
128
129 #ifndef _MSC_VER
130 void CSerial::openLinux()
131 {
132 termios newtio;
133
134 std::cout << "opening port " << std::endl;
135 mFiledescriptor = ::open(mPortstr, flags);
136 if (mFiledescriptor < 0)
137 throw std::runtime_error( writeLastError() );
138
139 std::cout << "port opened" << std::endl;
140 bzero(&newtio, sizeof(newtio) );
141
142 // use a std. 8N1 config
143 newtio.c_cflag = convertBaudrate(mBitrate) | CRTSCTS | CS8 | CLOCAL | CREAD;
144 newtio.c_iflag = IGNPAR;
145 newtio.c_oflag = 0;
146
147 // set input mode (non-canonical, no echo,...)
148 newtio.c_lflag = 0;
149
150 newtio.c_cc[VTIME] = 0; // inter-character timer unused
151 newtio.c_cc[VMIN] = 0; // blocking read until 1 chars received
152
153
154 /* cfmakeraw(&newtio);
155 cfsetospeed(&newtio, B9600 );
156 cfsetispeed(&newtio, B9600 );
157 */
158
159 tcflush(mFiledescriptor, TCIFLUSH);
160 tcsetattr(mFiledescriptor, TCSANOW, &newtio);
161
162 std::cout << "port configured " << std::endl;
163 mIsopen = true;
164 }
165 #endif
166
167 void CSerial::close()
168 {
169 if (mIsopen)
170 {
171 #ifdef _MSC_VER
172 while (getComstat().cbOutQue >0)
173 Sleep(5);
174 SetCommState(mComport,&mDcbRestore);
175 CloseHandle(mComport);
176 #else // linux close()
177 tcdrain(mFiledescriptor);
178 tcsetattr(mFiledescriptor, TCSADRAIN, &mOldtio); //restore settings, when all data is written
179 ::close(mFiledescriptor); //close()== system-call
180 #endif
181 mIsopen = false;
182 }
183 }
184
185
186 int CSerial::readByte()
187 {
188 unsigned char out;
189 unsigned long size;
190
191 if (!mIsopen)
192 throw std::runtime_error("Port not opened");
193 #ifdef _MSC_VER
194 ReadFile(mComport,&out,1,&size,0);
195 if (size != 1)
196 {
197 std::string error = writeLastError();
198 CloseHandle(mComport);
199 throw std::exception(error.c_str());
200 }
201 #else //linux readByte()
202 size = read(mFiledescriptor, &out, 1);
203 if (size != 1)
204 {
205 //std::cout << writeLastError() << std::endl;
206 return -1;
207 }
208 #endif
209
210 printByte("Read", out);
211 return out;
212 }
213
214
215 void CSerial::writeByte(unsigned char out)
216 {
217 unsigned long size;
218
219 printByte("Write", out);
220 if (!mIsopen)
221 throw std::runtime_error("Port not opened");
222
223 #ifdef _MSC_VER
224 while (getComstat().cbOutQue >0)
225 Sleep(2);
226
227 WriteFile(mComport,&out,1,&size, NULL);
228 if (size ==0)
229 {
230 std::string error = writeLastError();
231 CloseHandle(mComport);
232 throw std::exception(error.c_str());
233 }
234 #else //linux writeByte()
235 //tcdrain(mFiledescriptor);
236 size = write(mFiledescriptor,&out,1);
237 Sleep(50);
238 //tcdrain(mFiledescriptor);
239 if (size != 1)
240 throw std::runtime_error(writeLastError() );
241 #endif
242 }
243
244 int CSerial::convertBaudrate(Baudrate rate)
245 {
246 int retval=0;
247 std::cout << "Rate:" << rate << std::endl;
248 #ifdef _MSC_VER
249 switch( rate )
250 {
251 case Baud300:
252 retval = 300;
253 break;
254 case Baud600:
255 retval = 600;
256 break;
257 case Baud1200:
258 retval = 1200;
259 break;
260 case Baud2400:
261 retval = 2400;
262 break;
263 case Baud4800:
264 retval = 4800;
265 break;
266 case Baud9600:
267 retval = 9600;
268 break;
269 case Baud19200:
270 retval = 19200;
271 break;
272 case Baud38400:
273 retval = 38400;
274 break;
275 case Baud57600:
276 retval = 57600;
277 break;
278 case Baud11520:
279 retval = 115200;
280 break;
281 }
282 #else
283 switch (rate)
284 {
285 case Baud300:
286 retval = B300;
287 break;
288 case Baud600:
289 retval = B600;
290 break;
291 case Baud1200:
292 retval = B1200;
293 break;
294 case Baud2400:
295 retval = B2400;
296 break;
297 case Baud4800:
298 retval = B4800;
299 break;
300 case Baud9600:
301 retval = B9600;
302 break;
303 case Baud19200:
304 retval = B19200;
305 break;
306 case Baud38400:
307 retval = B38400;
308 break;
309 case Baud57600:
310 retval = B57600;
311 break;
312 case Baud115200:
313 retval = B115200;
314 break;
315 }
316 #endif
317
318 std::cout << "Rate: " << retval << "/" << B9600 << std::endl;
319 return retval;
320 }
321
322 #ifdef _MSC_VER
323 COMSTAT CSerial::getComstat() const
324 {
325 if (!mIsopen)
326 throw std::exception("Port not opened");
327
328 COMSTAT stat;
329 DWORD x;
330 ClearCommError(mComport,&x,&stat);
331 return stat;
332 }
333 #endif
334
335 int CSerial::bytesReady() const
336 {
337 #ifdef _MSC_VER
338 return getComstat().cbInQue;
339 #else
340 return 0;
341 #endif
342 }
343
344 int CSerial::outQueueSize() const
345 {
346 #ifdef _MSC_VER
347 return getComstat().cbOutQue;
348 #else
349 return 0;
350 #endif
351 }
352
353 // Debug function
354 //
355 void CSerial::printByte(char* description, unsigned char byte)
356 {
357 std::cout << description << " : " << (int) byte << "/" << std::setw(2) << std::setfill('0') << std::hex << (int) byte << std::endl;
358 std::cout << std::dec;
359 }
360
361
362 /*
363 void CSerial::writeBytes(UCVector out)
364 {
365 unsigned long bytesWritten;
366 unsigned int size = out.size();
367 unsigned char *buf = new unsigned char[size];
368
369 for (int i=0; i<size; i++)
370 buf[i] = out[i];
371
372 WriteFile(mComport,buf,size,&bytesWritten,NULL);
373 if (bytesWritten != size)
374 {
375 std::string error = writeLastError();
376 CloseHandle(mComport);
377 throw std::exception(error.c_str());
378 }
379 delete[] buf;
380 }
381 */
382
383
384 /*
385 UCVector CSerial::readBytes(int maxcount)
386 {
387 UCVector buf;
388
389
390
391 return buf;
392 }
393 */

  ViewVC Help
Powered by ViewVC 1.1.20