Commit 9c29783bfc17aef37b4cde583204ca6103e8b8c6
1 parent
5a48f672
Added baud rate configure unit tests.
Showing
3 changed files
with
73 additions
and
76 deletions
include/CppLinuxSerial/SerialPort.hpp
| @@ -22,11 +22,13 @@ | @@ -22,11 +22,13 @@ | ||
| 22 | namespace mn { | 22 | namespace mn { |
| 23 | namespace CppLinuxSerial { | 23 | namespace CppLinuxSerial { |
| 24 | 24 | ||
| 25 | -/// \brief Strongly-typed enumeration of baud rates for use with the SerialPort class | 25 | + /// \brief Strongly-typed enumeration of baud rates for use with the SerialPort class |
| 26 | enum class BaudRate { | 26 | enum class BaudRate { |
| 27 | - none, | ||
| 28 | - b9600, | ||
| 29 | - b57600 | 27 | + B_9600, |
| 28 | + B_38400, | ||
| 29 | + B_57600, | ||
| 30 | + B_115200, | ||
| 31 | + CUSTOM | ||
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| 32 | enum class State { | 34 | enum class State { |
| @@ -69,7 +71,7 @@ namespace mn { | @@ -69,7 +71,7 @@ namespace mn { | ||
| 69 | 71 | ||
| 70 | /// \brief Configures the tty device as a serial port. | 72 | /// \brief Configures the tty device as a serial port. |
| 71 | /// \warning Device must be open (valid file descriptor) when this is called. | 73 | /// \warning Device must be open (valid file descriptor) when this is called. |
| 72 | - void ConfigureDeviceAsSerialPort(); | 74 | + void ConfigureTermios(); |
| 73 | 75 | ||
| 74 | //! @brief Closes the COM port. | 76 | //! @brief Closes the COM port. |
| 75 | void Close(); | 77 | void Close(); |
src/SerialPort.cpp
| @@ -41,37 +41,13 @@ namespace CppLinuxSerial { | @@ -41,37 +41,13 @@ namespace CppLinuxSerial { | ||
| 41 | void SerialPort::SetDevice(const std::string& device) | 41 | void SerialPort::SetDevice(const std::string& device) |
| 42 | { | 42 | { |
| 43 | device_ = device; | 43 | device_ = device; |
| 44 | - ConfigureDeviceAsSerialPort(); | 44 | + ConfigureTermios(); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void SerialPort::SetBaudRate(BaudRate baudRate) | 47 | void SerialPort::SetBaudRate(BaudRate baudRate) |
| 48 | { | 48 | { |
| 49 | - | ||
| 50 | - // Get current termios struct | ||
| 51 | - termios myTermios = this->GetTermios(); | ||
| 52 | - | ||
| 53 | - switch(baudRate) | ||
| 54 | - { | ||
| 55 | - case BaudRate::none: | ||
| 56 | - // Error, baud rate has not been set yet | ||
| 57 | - throw std::runtime_error("Baud rate for '" + device_ + "' cannot be set to none."); | ||
| 58 | - break; | ||
| 59 | - case BaudRate::b9600: | ||
| 60 | - cfsetispeed(&myTermios, B9600); | ||
| 61 | - cfsetospeed(&myTermios, B9600); | ||
| 62 | - break; | ||
| 63 | - case BaudRate::b57600: | ||
| 64 | - cfsetispeed(&myTermios, B57600); | ||
| 65 | - cfsetospeed(&myTermios, B57600); | ||
| 66 | - break; | ||
| 67 | - } | ||
| 68 | - | ||
| 69 | - // Save back to file | ||
| 70 | - this->SetTermios(myTermios); | ||
| 71 | - | ||
| 72 | - // Setting the baudrate must of been successful, so we can now store this | ||
| 73 | - // new value internally. This must be done last! | ||
| 74 | baudRate_ = baudRate; | 49 | baudRate_ = baudRate; |
| 50 | + ConfigureTermios(); | ||
| 75 | } | 51 | } |
| 76 | 52 | ||
| 77 | void SerialPort::Open() | 53 | void SerialPort::Open() |
| @@ -102,7 +78,7 @@ namespace CppLinuxSerial { | @@ -102,7 +78,7 @@ namespace CppLinuxSerial { | ||
| 102 | throw std::runtime_error("Could not open device " + device_ + ". Is the device name correct and do you have read/write permission?"); | 78 | throw std::runtime_error("Could not open device " + device_ + ". Is the device name correct and do you have read/write permission?"); |
| 103 | } | 79 | } |
| 104 | 80 | ||
| 105 | - ConfigureDeviceAsSerialPort(); | 81 | + ConfigureTermios(); |
| 106 | 82 | ||
| 107 | std::cout << "COM port opened successfully." << std::endl; | 83 | std::cout << "COM port opened successfully." << std::endl; |
| 108 | 84 | ||
| @@ -120,45 +96,13 @@ namespace CppLinuxSerial { | @@ -120,45 +96,13 @@ namespace CppLinuxSerial { | ||
| 120 | this->SetTermios(settings); | 96 | this->SetTermios(settings); |
| 121 | } | 97 | } |
| 122 | 98 | ||
| 123 | - void SerialPort::ConfigureDeviceAsSerialPort() | 99 | + void SerialPort::ConfigureTermios() |
| 124 | { | 100 | { |
| 125 | std::cout << "Configuring COM port \"" << device_ << "\"." << std::endl; | 101 | std::cout << "Configuring COM port \"" << device_ << "\"." << std::endl; |
| 126 | 102 | ||
| 127 | //================== CONFIGURE ==================// | 103 | //================== CONFIGURE ==================// |
| 128 | 104 | ||
| 129 | - termios tty = this->GetTermios(); | ||
| 130 | - /*struct termios tty; | ||
| 131 | - memset(&tty, 0, sizeof(tty)); | ||
| 132 | - | ||
| 133 | - // Get current settings (will be stored in termios structure) | ||
| 134 | - if(tcgetattr(this->fileDesc, &tty) != 0) | ||
| 135 | - { | ||
| 136 | - // Error occurred | ||
| 137 | - this->sp->PrintError(SmartPrint::Ss() << "Could not get terminal attributes for \"" << this->filePath << "\" - " << strerror(errno)); | ||
| 138 | - //return false; | ||
| 139 | - return; | ||
| 140 | - }*/ | ||
| 141 | - | ||
| 142 | - //========================= SET UP BAUD RATES =========================// | ||
| 143 | - | ||
| 144 | - // this->SetBaudRate(BaudRate::b57600); | ||
| 145 | - | ||
| 146 | - /* | ||
| 147 | - switch(this->baudRate) | ||
| 148 | - { | ||
| 149 | - case BaudRates::none: | ||
| 150 | - // Error, baud rate has not been set yet | ||
| 151 | - this->sp->PrintError(SmartPrint::Ss() << "Baud rate for \"" << this->filePath << "\" has not been set."); | ||
| 152 | - return; | ||
| 153 | - case BaudRates::b9600: | ||
| 154 | - cfsetispeed(&tty, B9600); | ||
| 155 | - cfsetospeed(&tty, B9600); | ||
| 156 | - break; | ||
| 157 | - case BaudRates::b57600: | ||
| 158 | - cfsetispeed(&tty, B57600); | ||
| 159 | - cfsetospeed(&tty, B57600); | ||
| 160 | - break; | ||
| 161 | - }*/ | 105 | + termios tty = GetTermios(); |
| 162 | 106 | ||
| 163 | //================= (.c_cflag) ===============// | 107 | //================= (.c_cflag) ===============// |
| 164 | 108 | ||
| @@ -170,6 +114,32 @@ namespace CppLinuxSerial { | @@ -170,6 +114,32 @@ namespace CppLinuxSerial { | ||
| 170 | tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) | 114 | tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) |
| 171 | 115 | ||
| 172 | 116 | ||
| 117 | + //===================== BAUD RATE =================// | ||
| 118 | + | ||
| 119 | + switch(baudRate_) { | ||
| 120 | + case BaudRate::B_9600: | ||
| 121 | + cfsetispeed(&tty, B9600); | ||
| 122 | + cfsetospeed(&tty, B9600); | ||
| 123 | + break; | ||
| 124 | + case BaudRate::B_38400: | ||
| 125 | + cfsetispeed(&tty, B38400); | ||
| 126 | + cfsetospeed(&tty, B38400); | ||
| 127 | + break; | ||
| 128 | + case BaudRate::B_57600: | ||
| 129 | + cfsetispeed(&tty, B57600); | ||
| 130 | + cfsetospeed(&tty, B57600); | ||
| 131 | + break; | ||
| 132 | + case BaudRate::B_115200: | ||
| 133 | + cfsetispeed(&tty, B115200); | ||
| 134 | + cfsetospeed(&tty, B115200); | ||
| 135 | + break; | ||
| 136 | + case BaudRate::CUSTOM: | ||
| 137 | + // See https://gist.github.com/kennethryerson/f7d1abcf2633b7c03cf0 | ||
| 138 | + throw std::runtime_error("Custom baud rate not yet supported."); | ||
| 139 | + default: | ||
| 140 | + throw std::runtime_error(std::string() + "baudRate passed to " + __PRETTY_FUNCTION__ + " unrecognized."); | ||
| 141 | + } | ||
| 142 | + | ||
| 173 | //===================== (.c_oflag) =================// | 143 | //===================== (.c_oflag) =================// |
| 174 | 144 | ||
| 175 | tty.c_oflag = 0; // No remapping, no delays | 145 | tty.c_oflag = 0; // No remapping, no delays |
| @@ -180,7 +150,7 @@ namespace CppLinuxSerial { | @@ -180,7 +150,7 @@ namespace CppLinuxSerial { | ||
| 180 | // c_cc[WMIN] sets the number of characters to block (wait) for when read() is called. | 150 | // c_cc[WMIN] sets the number of characters to block (wait) for when read() is called. |
| 181 | // Set to 0 if you don't want read to block. Only meaningful when port set to non-canonical mode | 151 | // Set to 0 if you don't want read to block. Only meaningful when port set to non-canonical mode |
| 182 | //tty.c_cc[VMIN] = 1; | 152 | //tty.c_cc[VMIN] = 1; |
| 183 | - this->SetNumCharsToWait(1); | 153 | + SetNumCharsToWait(1); |
| 184 | 154 | ||
| 185 | // c_cc[VTIME] sets the inter-character timer, in units of 0.1s. | 155 | // c_cc[VTIME] sets the inter-character timer, in units of 0.1s. |
| 186 | // Only meaningful when port is set to non-canonical mode | 156 | // Only meaningful when port is set to non-canonical mode |
| @@ -219,21 +189,19 @@ namespace CppLinuxSerial { | @@ -219,21 +189,19 @@ namespace CppLinuxSerial { | ||
| 219 | }*/ | 189 | }*/ |
| 220 | } | 190 | } |
| 221 | 191 | ||
| 222 | - void SerialPort::SetNumCharsToWait(uint32_t numCharsToWait) | ||
| 223 | - { | 192 | + void SerialPort::SetNumCharsToWait(uint32_t numCharsToWait) { |
| 224 | // Get current termios struct | 193 | // Get current termios struct |
| 225 | - termios myTermios = this->GetTermios(); | 194 | + termios myTermios = GetTermios(); |
| 226 | 195 | ||
| 227 | // Save the number of characters to wait for | 196 | // Save the number of characters to wait for |
| 228 | // to the control register | 197 | // to the control register |
| 229 | myTermios.c_cc[VMIN] = numCharsToWait; | 198 | myTermios.c_cc[VMIN] = numCharsToWait; |
| 230 | 199 | ||
| 231 | // Save termios back | 200 | // Save termios back |
| 232 | - this->SetTermios(myTermios); | 201 | + SetTermios(myTermios); |
| 233 | } | 202 | } |
| 234 | 203 | ||
| 235 | - void SerialPort::Write(const std::string& data) | ||
| 236 | - { | 204 | + void SerialPort::Write(const std::string& data) { |
| 237 | if(fileDesc_ == 0) { | 205 | if(fileDesc_ == 0) { |
| 238 | //this->sp->PrintError(SmartPrint::Ss() << ); | 206 | //this->sp->PrintError(SmartPrint::Ss() << ); |
| 239 | //return false; | 207 | //return false; |
test/unit/BasicTests.cpp
| @@ -53,16 +53,43 @@ namespace { | @@ -53,16 +53,43 @@ namespace { | ||
| 53 | EXPECT_EQ(true, true); | 53 | EXPECT_EQ(true, true); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | + TEST_F(BasicTests, BaudRateSetCorrectly) { | ||
| 57 | + SerialPort serialPort0(device0_, BaudRate::B_57600); | ||
| 58 | + serialPort0.Open(); | ||
| 59 | + auto retVal = TestUtil::Exec("stty -a -F " + device0_); | ||
| 60 | + EXPECT_NE(std::string::npos, retVal.find("speed 57600 baud")); | ||
| 61 | + | ||
| 62 | + serialPort0.SetBaudRate(BaudRate::B_115200); | ||
| 63 | + retVal = TestUtil::Exec("stty -a -F " + device0_); | ||
| 64 | + EXPECT_NE(std::string::npos, retVal.find("speed 115200 baud")); | ||
| 65 | + } | ||
| 66 | + | ||
| 56 | TEST_F(BasicTests, CanOpen) { | 67 | TEST_F(BasicTests, CanOpen) { |
| 57 | - SerialPort serialPort0(device0_, BaudRate::b57600); | 68 | + SerialPort serialPort0(device0_, BaudRate::B_57600); |
| 58 | serialPort0.Open(); | 69 | serialPort0.Open(); |
| 59 | } | 70 | } |
| 60 | 71 | ||
| 61 | TEST_F(BasicTests, ReadWrite) { | 72 | TEST_F(BasicTests, ReadWrite) { |
| 62 | - SerialPort serialPort0(device0_, BaudRate::b57600); | 73 | + SerialPort serialPort0(device0_, BaudRate::B_57600); |
| 74 | + serialPort0.Open(); | ||
| 75 | + | ||
| 76 | + SerialPort serialPort1(device1_, BaudRate::B_57600); | ||
| 77 | + serialPort1.Open(); | ||
| 78 | + | ||
| 79 | + serialPort0.Write("Hello"); | ||
| 80 | + | ||
| 81 | + std::string readData; | ||
| 82 | + serialPort1.Read(readData); | ||
| 83 | + | ||
| 84 | + ASSERT_EQ("Hello", readData); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + | ||
| 88 | + TEST_F(BasicTests, ReadWriteDiffBaudRates) { | ||
| 89 | + SerialPort serialPort0(device0_, BaudRate::B_9600); | ||
| 63 | serialPort0.Open(); | 90 | serialPort0.Open(); |
| 64 | 91 | ||
| 65 | - SerialPort serialPort1(device1_, BaudRate::b57600); | 92 | + SerialPort serialPort1(device1_, BaudRate::B_57600); |
| 66 | serialPort1.Open(); | 93 | serialPort1.Open(); |
| 67 | 94 | ||
| 68 | serialPort0.Write("Hello"); | 95 | serialPort0.Write("Hello"); |