diff --git a/.gitignore b/.gitignore
index 1fc2c47..a749124 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,7 @@ cmake-build-debug/
.vscode/
# Sphinx build dir
-docs/_build/
\ No newline at end of file
+docs/_build/
+
+# Build artifacts
+a.out
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b85fa4..8902279 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
+## [v2.1.0] - 2020-11-08
+
+### Added
+- Support for custom baud rates.
+- Support for all standard UNIX baud rates.
+- Improved Doxygen documentation.
+- Improved README.md documentation.
+
+### Removed
+- Dependencies from the README, they weren't that useful and were not accurate anyway.
+
## [v2.0.3] - 2020-10-13
### Added
diff --git a/README.md b/README.md
index 1a4582c..caea473 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# CppLinuxSerial
-Serial port library written in C++
+Linux serial port library written in C++.
[](https://travis-ci.org/gbmhunter/CppLinuxSerial)
@@ -8,7 +8,9 @@ Serial port library written in C++
Library for communicating with COM ports on a Linux system.
-Uses fstream to the file I/O.
+* Simple API
+* Supports custom baud rates
+* cmake based build system
## Installation
@@ -67,13 +69,14 @@ using namespace mn::CppLinuxSerial;
int main() {
// Create serial port object and open serial port
SerialPort serialPort("/dev/ttyUSB0", BaudRate::B_57600);
+ // Use SerialPort serialPort("/dev/ttyACM0", 13000); instead if you want to provide a custom baud rate
serialPort.SetTimeout(-1); // Block when reading until any data is received
serialPort.Open();
// Write some ASCII datae
serialPort.Write("Hello");
- // Read some data back
+ // Read some data back (will block until at least 1 byte is received due to the SetTimeout(-1) call above)
std::string readData;
serialPort.Read(readData);
@@ -88,34 +91,7 @@ If the above code was in a file called `main.cpp` and you had installed `CppLinu
g++ main.cpp -lCppLinuxSerial
```
-For more examples, see the `.cpp` files in `test/unit/`.
-
-## Dependencies
-
-The following table lists all of the libraries dependencies.
-
-
-
-
- | Dependency |
- Comments |
-
-
-
-
- | C++14 |
- C++14 used for strongly typed enums, `std::chrono` and literals. |
-
-
- | stdio.h |
- snprintf() |
-
-
- | stty |
- Used in unit tests to verify the serial port is configured correctly. |
-
-
-
+For more examples, see the files in `test/`.
## Issues
@@ -123,7 +99,7 @@ See GitHub Issues.
## FAQ
-1. My code stalls when calling functions like `SerialPort::Read()`. This is probably because the library is set up to do a blocking read, and not enough characters have been received to allow `SerialPort::Read()` to return. Use `SerialPort::SetNumCharsToWait()` to determine how many characters to wait for before returning (set to 0 for non-blocking mode).
+1. My code stalls when calling functions like `SerialPort::Read()`. This is probably because the library is set up to do a blocking read, and not enough characters have been received to allow `SerialPort::Read()` to return. Call `SerialPort::SetTimeout(0)` before the serial port is open to set a non-blocking mode.
## Changelog
diff --git a/include/CppLinuxSerial/SerialPort.hpp b/include/CppLinuxSerial/SerialPort.hpp
index afc6d38..6739e7a 100644
--- a/include/CppLinuxSerial/SerialPort.hpp
+++ b/include/CppLinuxSerial/SerialPort.hpp
@@ -24,22 +24,11 @@
// User headers
#include "Exception.hpp"
-
- typedef unsigned int speed_t;
-// typedef struct termios2 {
-// tcflag_t c_iflag; /* input mode flags */
-// tcflag_t c_oflag; /* output mode flags */
-// tcflag_t c_cflag; /* control mode flags */
-// tcflag_t c_lflag; /* local mode flags */
-// cc_t c_line; /* line discipline */
-// cc_t c_cc[NCCS]; /* control characters */
-// speed_t c_ispeed; /* input speed */
-// speed_t c_ospeed; /* output speed */
-// } termios2_t;
-
namespace mn {
namespace CppLinuxSerial {
+ /// \brief Represents the baud rate "types" that can be used with the serial port. STANDARD represents all
+ /// the standard baud rates as provided by UNIX, CUSTOM represents a baud rate defined by an arbitray integer.
enum class BaudRateType {
STANDARD,
CUSTOM,
@@ -72,6 +61,7 @@ namespace mn {
B_CUSTOM, // Placeholder
};
+ /// \brief Represents the state of the serial port.
enum class State {
CLOSED,
OPEN,
@@ -90,13 +80,14 @@ namespace mn {
/// \brief Constructor that sets up serial port with the basic (required) parameters.
SerialPort(const std::string &device, speed_t baudRate);
- //! @brief Destructor. Closes serial port if still open.
+ /// \brief Destructor. Closes serial port if still open.
virtual ~SerialPort();
/// \brief Sets the device to use for serial port communications.
/// \details Method can be called when serial port is in any state.
void SetDevice(const std::string &device);
+ /// \brief Allows the user to set a standard baud rate.
void SetBaudRate(BaudRate baudRate);
/// \brief Allows the user to set a custom baud rate.
@@ -139,15 +130,16 @@ namespace mn {
/// \brief Returns a populated termios structure for the passed in file descriptor.
// termios GetTermios();
-
-
/// \brief Configures the tty device as a serial port.
/// \warning Device must be open (valid file descriptor) when this is called.
void ConfigureTermios();
// void SetTermios(termios myTermios);
+ /// \brief Returns a populated termios2 structure for the serial port pointed to by the file descriptor.
termios2 GetTermios2();
+
+ /// \brief Assigns the provided tty settings to the serial port pointed to by the file descriptor.
void SetTermios2(termios2 tty);
/// \brief Keeps track of the serial port's state.
diff --git a/src/SerialPort.cpp b/src/SerialPort.cpp
index 72feedd..d3f09fa 100644
--- a/src/SerialPort.cpp
+++ b/src/SerialPort.cpp
@@ -140,103 +140,140 @@ namespace CppLinuxSerial {
//===================== BAUD RATE =================//
- // We used to use cfsetispeed() cand cfsetospeed(), but this didn't allow
- // us to set custom baud rates
+ // We used to use cfsetispeed() and cfsetospeed() with the B... macros, but this didn't allow
+ // us to set custom baud rates. So now to support both standard and custom baud rates lets
+ // just make everything "custom". This giant switch statement could be replaced with a map/lookup
+ // in the future
if (baudRateType_ == BaudRateType::STANDARD) {
+ tty.c_cflag &= ~CBAUD;
+ tty.c_cflag |= CBAUDEX;
switch(baudRateStandard_) {
- // case BaudRate::B_0:
+ case BaudRate::B_0:
// cfsetispeed(&tty, B0);
// cfsetospeed(&tty, B0);
- // tty.c_ispeed = 0;
- // tty.c_ospeed = 0;
- // break;
- // case BaudRate::B_50:
+ tty.c_ispeed = 0;
+ tty.c_ospeed = 0;
+ break;
+ case BaudRate::B_50:
// cfsetispeed(&tty, B50);
// cfsetospeed(&tty, B50);
- // tty.c_ispeed = 50;
- // tty.c_ospeed = 50;
- // break;
- // case BaudRate::B_75:
- // cfsetispeed(&tty, B75);
- // cfsetospeed(&tty, B75);
- // break;
- // case BaudRate::B_110:
- // cfsetispeed(&tty, B110);
- // cfsetospeed(&tty, B110);
- // break;
- // case BaudRate::B_134:
- // cfsetispeed(&tty, B134);
- // cfsetospeed(&tty, B134);
- // break;
- // case BaudRate::B_150:
- // cfsetispeed(&tty, B150);
- // cfsetospeed(&tty, B150);
- // break;
- // case BaudRate::B_200:
- // cfsetispeed(&tty, B200);
- // cfsetospeed(&tty, B200);
- // break;
- // case BaudRate::B_300:
- // cfsetispeed(&tty, B300);
- // cfsetospeed(&tty, B300);
- // break;
- // case BaudRate::B_600:
- // cfsetispeed(&tty, B600);
- // cfsetospeed(&tty, B600);
- // break;
- // case BaudRate::B_1200:
- // cfsetispeed(&tty, B1200);
- // cfsetospeed(&tty, B1200);
- // break;
- // case BaudRate::B_1800:
- // cfsetispeed(&tty, B1800);
- // cfsetospeed(&tty, B1800);
- // break;
- // case BaudRate::B_2400:
- // cfsetispeed(&tty, B2400);
- // cfsetospeed(&tty, B2400);
- // break;
- // case BaudRate::B_4800:
- // cfsetispeed(&tty, B4800);
- // cfsetospeed(&tty, B4800);
- // break;
- // case BaudRate::B_9600:
+ tty.c_ispeed = 50;
+ tty.c_ospeed = 50;
+ break;
+ case BaudRate::B_75:
+ // cfsetispeed(&tty, B75);
+ // cfsetospeed(&tty, B75);
+ tty.c_ispeed = 75;
+ tty.c_ospeed = 75;
+ break;
+ case BaudRate::B_110:
+ // cfsetispeed(&tty, B110);
+ // cfsetospeed(&tty, B110);
+ tty.c_ispeed = 110;
+ tty.c_ospeed = 110;
+ break;
+ case BaudRate::B_134:
+ // cfsetispeed(&tty, B134);
+ // cfsetospeed(&tty, B134);
+ tty.c_ispeed = 134;
+ tty.c_ospeed = 134;
+ break;
+ case BaudRate::B_150:
+ // cfsetispeed(&tty, B150);
+ // cfsetospeed(&tty, B150);
+ tty.c_ispeed = 150;
+ tty.c_ospeed = 150;
+ break;
+ case BaudRate::B_200:
+ // cfsetispeed(&tty, B200);
+ // cfsetospeed(&tty, B200);
+ tty.c_ispeed = 200;
+ tty.c_ospeed = 200;
+ break;
+ case BaudRate::B_300:
+ // cfsetispeed(&tty, B300);
+ // cfsetospeed(&tty, B300);
+ tty.c_ispeed = 300;
+ tty.c_ospeed = 300;
+ break;
+ case BaudRate::B_600:
+ // cfsetispeed(&tty, B600);
+ // cfsetospeed(&tty, B600);
+ tty.c_ispeed = 600;
+ tty.c_ospeed = 600;
+ break;
+ case BaudRate::B_1200:
+ // cfsetispeed(&tty, B1200);
+ // cfsetospeed(&tty, B1200);
+ tty.c_ispeed = 1200;
+ tty.c_ospeed = 1200;
+ break;
+ case BaudRate::B_1800:
+ // cfsetispeed(&tty, B1800);
+ // cfsetospeed(&tty, B1800);
+ tty.c_ispeed = 1800;
+ tty.c_ospeed = 1800;
+ break;
+ case BaudRate::B_2400:
+ // cfsetispeed(&tty, B2400);
+ // cfsetospeed(&tty, B2400);
+ tty.c_ispeed = 2400;
+ tty.c_ospeed = 2400;
+ break;
+ case BaudRate::B_4800:
+ // cfsetispeed(&tty, B4800);
+ // cfsetospeed(&tty, B4800);
+ tty.c_ispeed = 4800;
+ tty.c_ospeed = 4800;
+ break;
+ case BaudRate::B_9600:
// cfsetispeed(&tty, B9600);
// cfsetospeed(&tty, B9600);
- // tty.c_ispeed = 9600;
- // tty.c_ospeed = 9600;
- // break;
- // case BaudRate::B_19200:
- // cfsetispeed(&tty, B19200);
- // cfsetospeed(&tty, B19200);
- // break;
- // case BaudRate::B_38400:
- // cfsetispeed(&tty, B38400);
- // cfsetospeed(&tty, B38400);
- // break;
- // case BaudRate::B_57600:
- // cfsetispeed(&tty, B57600);
- // cfsetospeed(&tty, B57600);
- // break;
- // case BaudRate::B_115200:
- // cfsetispeed(&tty, B115200);
- // cfsetospeed(&tty, B115200);
- // break;
- // case BaudRate::B_230400:
- // cfsetispeed(&tty, B230400);
- // cfsetospeed(&tty, B230400);
- // break;
- // case BaudRate::B_460800:
- // cfsetispeed(&tty, B460800);
- // cfsetospeed(&tty, B460800);
- // break;
- // case BaudRate::CUSTOM:
- // // See https://gist.github.com/kennethryerson/f7d1abcf2633b7c03cf0
- // throw std::runtime_error("Custom baud rate not yet supported.");
+ tty.c_ispeed = 9600;
+ tty.c_ospeed = 9600;
+ break;
+ case BaudRate::B_19200:
+ // cfsetispeed(&tty, B19200);
+ // cfsetospeed(&tty, B19200);
+ tty.c_ispeed = 19200;
+ tty.c_ospeed = 19200;
+ break;
+ case BaudRate::B_38400:
+ // cfsetispeed(&tty, B38400);
+ // cfsetospeed(&tty, B38400);
+ tty.c_ispeed = 38400;
+ tty.c_ospeed = 38400;
+ break;
+ case BaudRate::B_57600:
+ // cfsetispeed(&tty, B57600);
+ // cfsetospeed(&tty, B57600);
+ tty.c_ispeed = 57600;
+ tty.c_ospeed = 57600;
+ break;
+ case BaudRate::B_115200:
+ // cfsetispeed(&tty, B115200);
+ // cfsetospeed(&tty, B115200);
+ tty.c_ispeed = 115200;
+ tty.c_ospeed = 115200;
+ break;
+ case BaudRate::B_230400:
+ // cfsetispeed(&tty, B230400);
+ // cfsetospeed(&tty, B230400);
+ tty.c_ispeed = 230400;
+ tty.c_ospeed = 230400;
+ break;
+ case BaudRate::B_460800:
+ // cfsetispeed(&tty, B460800);
+ // cfsetospeed(&tty, B460800);
+ tty.c_ispeed = 460800;
+ tty.c_ospeed = 460800;
+ break;
default:
throw std::runtime_error(std::string() + "baudRate passed to " + __PRETTY_FUNCTION__ + " unrecognized.");
}
}
+ // This does no different than STANDARD atm, but let's keep
+ // them separate for now....
else if (baudRateType_ == BaudRateType::CUSTOM)
{
tty.c_cflag &= ~CBAUD;
@@ -300,14 +337,11 @@ namespace CppLinuxSerial {
tty.c_cc[VMIN] = 0;
}
-
//======================== (.c_iflag) ====================//
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
-
-
//=========================== LOCAL MODES (c_lflag) =======================//
// Canonical input is when read waits for EOL or EOF characters before returning. In non-canonical mode, the rate at which
@@ -319,7 +353,6 @@ namespace CppLinuxSerial {
tty.c_lflag &= ~ISIG; // Disables recognition of INTR (interrupt), QUIT and SUSP (suspend) characters
-
// Try and use raw function call
//cfmakeraw(&tty);
diff --git a/test/arduino/Basic/Basic.ino b/test/arduino/Basic/Basic.ino
index d9a4a20..10fa637 100644
--- a/test/arduino/Basic/Basic.ino
+++ b/test/arduino/Basic/Basic.ino
@@ -13,7 +13,7 @@
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
- Serial.begin(13000);
+ Serial.begin(9600);
// Serial.begin(81234); // Used to test custom baud rates
}
diff --git a/test/arduino/main.cpp b/test/arduino/main.cpp
index 935d756..0cf1248 100644
--- a/test/arduino/main.cpp
+++ b/test/arduino/main.cpp
@@ -4,8 +4,8 @@ using namespace mn::CppLinuxSerial;
int main() {
// Create serial port object and open serial port
- // SerialPort serialPort("/dev/ttyACM0", BaudRate::B_9600);
- SerialPort serialPort("/dev/ttyACM0", 13000);
+ SerialPort serialPort("/dev/ttyACM0", BaudRate::B_9600);
+ // SerialPort serialPort("/dev/ttyACM0", 13000);
serialPort.SetTimeout(-1); // Block when reading until any data is received
serialPort.Open();