SerialIO.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 //#include "stdafx.h"
20 #include <math.h>
21 #include <string.h>
22 #include <iostream>
23 
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29 #include <linux/serial.h>
30 #include <unistd.h>
31 #include <termios.h>
32 
33 
34 
35 //#define _PRINT_BYTES
36 
37 /*
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #undef THIS_FILE
41 static char THIS_FILE[] = __FILE__;
42 #endif
43 */
44 
45 
46 bool getBaudrateCode(int iBaudrate, int* iBaudrateCode)
47 {
48  // baudrate codes are defined in termios.h
49  // currently upto B1000000
50  const int baudTable[] = {
51  0, 50, 75, 110, 134, 150, 200, 300, 600,
52  1200, 1800, 2400, 4800,
53  9600, 19200, 38400, 57600, 115200, 230400,
54  460800, 500000, 576000, 921600, 1000000
55  };
56  const int baudCodes[] = {
57  B0, B50, B75, B110, B134, B150, B200, B300, B600,
58  B1200, B1800, B2400, B4800,
59  B9600, B19200, B38400, B57600, B115200, B230400,
60  B460800, B500000, B576000, B921600, B1000000
61  };
62  const int iBaudsLen = sizeof(baudTable) / sizeof(int);
63 
64  bool ret = false;
65  *iBaudrateCode = B38400;
66  int i;
67  for( i=0; i<iBaudsLen; i++ ) {
68  if( baudTable[i] == iBaudrate ) {
69  *iBaudrateCode = baudCodes[i];
70  ret = true;
71  break;
72  }
73  }
74  /*
75  int iStart = 0;
76  int iEnd = iBaudsLen;
77  int iPos = (iStart + iEnd) / 2;
78  while ( iPos + 1 < iBaudsLen
79  && (iBaudrate < baudTable[iPos] || iBaudrate >= baudTable[iPos + 1])
80  && iPos != 0)
81  {
82  if (iBaudrate < baudTable[iPos])
83  {
84  iEnd = iPos;
85  }
86  else
87  {
88  iStart = iPos;
89  }
90  iPos = (iStart + iEnd) / 2;
91  }
92 
93  return baudCodes[iPos];
94  */
95  return ret;
96 }
97 
98 
99 
100 
102 // Konstruktion/Destruktion
104 
106  : m_DeviceName(""),
107  m_Device(-1),
108  m_BaudRate(9600),
109  m_Multiplier(1.0),
110  m_ByteSize(8),
111  m_StopBits(SB_ONE),
112  m_Parity(PA_NONE),
113  m_Handshake(HS_NONE),
114  m_ReadBufSize(1024),
115  m_WriteBufSize(m_ReadBufSize),
116  m_Timeout(0),
117  m_ShortBytePeriod(false)
118 {
119  m_BytePeriod.tv_sec = 0;
120  m_BytePeriod.tv_usec = 0;
121 }
122 
124 {
125  closeIO();
126 }
127 
129 {
130  int Res;
131 
132  // open device
133  m_Device = open(m_DeviceName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
134 
135  if(m_Device < 0)
136  {
137  //RF_ERR("Open " << m_DeviceName << " failed, error code " << errno);
138  std::cout << "Trying to open " << m_DeviceName << " failed: "
139  << strerror(errno) << " (Error code " << errno << ")";
140 
141  return -1;
142  }
143 
144  // set parameters
145  Res = tcgetattr(m_Device, &m_tio);
146  if (Res == -1)
147  {
148  std::cerr << "tcgetattr of " << m_DeviceName << " failed: "
149  << strerror(errno) << " (Error code " << errno << ")";
150 
151  close(m_Device);
152  m_Device = -1;
153 
154  return -1;
155  }
156 
157  // Default values
158  m_tio.c_iflag = 0;
159  m_tio.c_oflag = 0;
160  m_tio.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
161  m_tio.c_lflag = 0;
162  cfsetispeed(&m_tio, B9600);
163  cfsetospeed(&m_tio, B9600);
164 
165  m_tio.c_cc[VINTR] = 3; // Interrupt
166  m_tio.c_cc[VQUIT] = 28; // Quit
167  m_tio.c_cc[VERASE] = 127; // Erase
168  m_tio.c_cc[VKILL] = 21; // Kill-line
169  m_tio.c_cc[VEOF] = 4; // End-of-file
170  m_tio.c_cc[VTIME] = 0; // Time to wait for data (tenths of seconds)
171  m_tio.c_cc[VMIN] = 1; // Minimum number of characters to read
172  m_tio.c_cc[VSWTC] = 0;
173  m_tio.c_cc[VSTART] = 17;
174  m_tio.c_cc[VSTOP] = 19;
175  m_tio.c_cc[VSUSP] = 26;
176  m_tio.c_cc[VEOL] = 0; // End-of-line
177  m_tio.c_cc[VREPRINT] = 18;
178  m_tio.c_cc[VDISCARD] = 15;
179  m_tio.c_cc[VWERASE] = 23;
180  m_tio.c_cc[VLNEXT] = 22;
181  m_tio.c_cc[VEOL2] = 0; // Second end-of-line
182 
183 
184  // set baud rate
185  int iNewBaudrate = int(m_BaudRate * m_Multiplier + 0.5);
186  std::cerr << "Setting Baudrate to " << iNewBaudrate;
187 
188  int iBaudrateCode = 0;
189  bool bBaudrateValid = getBaudrateCode(iNewBaudrate, &iBaudrateCode);
190 
191  cfsetispeed(&m_tio, iBaudrateCode);
192  cfsetospeed(&m_tio, iBaudrateCode);
193 
194  if( !bBaudrateValid ) {
195  std::cerr << "Baudrate code not available - setting baudrate directly";
196  struct serial_struct ss;
197  ioctl( m_Device, TIOCGSERIAL, &ss );
198  ss.flags |= ASYNC_SPD_CUST;
199  ss.custom_divisor = ss.baud_base / iNewBaudrate;
200  ioctl( m_Device, TIOCSSERIAL, &ss );
201  }
202 
203 
204  // set data format
205  m_tio.c_cflag &= ~CSIZE;
206  switch (m_ByteSize)
207  {
208  case 5:
209  m_tio.c_cflag |= CS5;
210  break;
211  case 6:
212  m_tio.c_cflag |= CS6;
213  break;
214  case 7:
215  m_tio.c_cflag |= CS7;
216  break;
217  case 8:
218  default:
219  m_tio.c_cflag |= CS8;
220  }
221 
222  m_tio.c_cflag &= ~ (PARENB | PARODD);
223 
224  switch (m_Parity)
225  {
226  case PA_ODD:
227  m_tio.c_cflag |= PARODD;
228  //break; // break must not be active here as we need the combination of PARODD and PARENB on odd parity.
229 
230  case PA_EVEN:
231  m_tio.c_cflag |= PARENB;
232  break;
233 
234  case PA_NONE:
235  default: {}
236  }
237 
238  switch (m_StopBits)
239  {
240  case SB_TWO:
241  m_tio.c_cflag |= CSTOPB;
242  break;
243 
244  case SB_ONE:
245  default:
246  m_tio.c_cflag &= ~CSTOPB;
247  }
248 
249  // hardware handshake
250  switch (m_Handshake)
251  {
252  case HS_NONE:
253  m_tio.c_cflag &= ~CRTSCTS;
254  m_tio.c_iflag &= ~(IXON | IXOFF | IXANY);
255  break;
256  case HS_HARDWARE:
257  m_tio.c_cflag |= CRTSCTS;
258  m_tio.c_iflag &= ~(IXON | IXOFF | IXANY);
259  break;
260  case HS_XONXOFF:
261  m_tio.c_cflag &= ~CRTSCTS;
262  m_tio.c_iflag |= (IXON | IXOFF | IXANY);
263  break;
264  }
265 
266  m_tio.c_oflag &= ~OPOST;
267  m_tio.c_lflag &= ~ICANON;
268 
269  // write parameters
270  Res = tcsetattr(m_Device, TCSANOW, &m_tio);
271 
272  if (Res == -1)
273  {
274  std::cerr << "tcsetattr " << m_DeviceName << " failed: "
275  << strerror(errno) << " (Error code " << errno << ")";
276 
277  close(m_Device);
278  m_Device = -1;
279 
280  return -1;
281  }
282 
283  // set buffer sizes
284 // SetupComm(m_Device, m_ReadBufSize, m_WriteBufSize);
285 
286  // set timeout
288 
289  return 0;
290 }
291 
293 {
294  if (m_Device != -1)
295  {
296  close(m_Device);
297  m_Device = -1;
298  }
299 }
300 
301 void SerialIO::setTimeout(double Timeout)
302 {
303  m_Timeout = Timeout;
304  if (m_Device != -1)
305  {
306  m_tio.c_cc[VTIME] = cc_t(ceil(m_Timeout * 10.0));
307  tcsetattr(m_Device, TCSANOW, &m_tio);
308  }
309 
310 }
311 
312 void SerialIO::setBytePeriod(double Period)
313 {
314  m_ShortBytePeriod = false;
315  m_BytePeriod.tv_sec = time_t(Period);
316  m_BytePeriod.tv_usec = suseconds_t((Period - m_BytePeriod.tv_sec) * 1000);
317 }
318 
319 //-----------------------------------------------
320 void SerialIO::changeBaudRate(int iBaudRate)
321 {
322  /*
323  int iRetVal;
324 
325  m_BaudRate = iBaudRate;
326 
327  int iNewBaudrate = int(m_BaudRate * m_Multiplier + 0.5);
328  int iBaudrateCode = getBaudrateCode(iNewBaudrate);
329  cfsetispeed(&m_tio, iBaudrateCode);
330  cfsetospeed(&m_tio, iBaudrateCode);
331 
332  iRetVal = tcsetattr(m_Device, TCSANOW, &m_tio);
333  if(iRetVal == -1)
334  {
335  LOG_OUT("error in SerialCom::changeBaudRate()");
336  char c;
337  std::cin >> c;
338  exit(0);
339  }*/
340 }
341 
342 
343 int SerialIO::readBlocking(char *Buffer, int Length)
344 {
345  ssize_t BytesRead;
346  BytesRead = read(m_Device, Buffer, Length);
347 #ifdef PRINT_BYTES
348  printf("%2d Bytes read:", BytesRead);
349  for(int i=0; i<BytesRead; i++)
350  printf(" %.2x", (unsigned char)Buffer[i]);
351  printf("\n");
352 #endif
353  return BytesRead;
354 }
355 
356 int SerialIO::readNonBlocking(char *Buffer, int Length)
357 {
358  int iAvaibleBytes = getSizeRXQueue();
359  int iBytesToRead = (Length < iAvaibleBytes) ? Length : iAvaibleBytes;
360  ssize_t BytesRead;
361 
362 
363  BytesRead = read(m_Device, Buffer, iBytesToRead);
364 
365 
366  // Debug
367 // printf("%2d Bytes read:", BytesRead);
368 // for(int i=0; i<BytesRead; i++)
369 // {
370 // unsigned char uc = (unsigned char)Buffer[i];
371 // printf(" %u", (unsigned int) uc );
372 // }
373 // printf("\n");
374 
375 
376  return BytesRead;
377 }
378 
379 int SerialIO::writeIO(const char *Buffer, int Length)
380 {
381  ssize_t BytesWritten;
382 
383  if (m_BytePeriod.tv_usec || m_BytePeriod.tv_sec)
384  {
385  int i;
386  for (i = 0; i < Length; i++)
387  {
388  BytesWritten = write(m_Device, Buffer + i, 1);
389  if (BytesWritten != 1)
390  break;
391  select(0, 0, 0, 0, &m_BytePeriod);
392  }
393  BytesWritten = i;
394  }
395  else
396  BytesWritten = write(m_Device, Buffer, Length);
397 #ifdef PRINT_BYTES
398  printf("%2d Bytes sent:", BytesWritten);
399  for(int i=0; i<BytesWritten; i++)
400  printf(" %.2x", (unsigned char)Buffer[i]);
401  printf("\n");
402 #endif
403 
404  return BytesWritten;
405 }
406 
408 {
409  int cbInQue;
410  int Res = ioctl(m_Device, FIONREAD, &cbInQue);
411  if (Res == -1) {
412  return 0;
413  }
414  return cbInQue;
415 }
416 
417 
int getSizeRXQueue()
Definition: SerialIO.cpp:407
void setBytePeriod(double Period)
Definition: SerialIO.cpp:312
int m_Device
Definition: SerialIO.h:199
std::string m_DeviceName
Definition: SerialIO.h:198
int m_StopBits
Definition: SerialIO.h:202
void closeIO()
Definition: SerialIO.cpp:292
virtual ~SerialIO()
Destructor.
Definition: SerialIO.cpp:123
HandshakeFlags m_Handshake
Definition: SerialIO.h:204
void setTimeout(double Timeout)
Definition: SerialIO.cpp:301
int m_BaudRate
Definition: SerialIO.h:200
::termios m_tio
Definition: SerialIO.h:197
void changeBaudRate(int BaudRate)
Definition: SerialIO.cpp:320
int writeIO(const char *Buffer, int Length)
Definition: SerialIO.cpp:379
int readBlocking(char *Buffer, int Length)
Definition: SerialIO.cpp:343
bool m_ShortBytePeriod
Definition: SerialIO.h:208
SerialIO()
Default constructor.
Definition: SerialIO.cpp:105
double m_Timeout
Definition: SerialIO.h:206
int readNonBlocking(char *Buffer, int Length)
Definition: SerialIO.cpp:356
ParityFlags m_Parity
Definition: SerialIO.h:203
int m_ByteSize
Definition: SerialIO.h:202
double m_Multiplier
Definition: SerialIO.h:201
int openIO()
Definition: SerialIO.cpp:128
::timeval m_BytePeriod
Definition: SerialIO.h:207
bool getBaudrateCode(int iBaudrate, int *iBaudrateCode)
Definition: SerialIO.cpp:46


cob_relayboard
Author(s): Christian Connette
autogenerated on Wed Apr 7 2021 02:11:46