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 | 22 | namespace mn { |
| 23 | 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 | 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 | 34 | enum class State { |
| ... | ... | @@ -69,7 +71,7 @@ namespace mn { |
| 69 | 71 | |
| 70 | 72 | /// \brief Configures the tty device as a serial port. |
| 71 | 73 | /// \warning Device must be open (valid file descriptor) when this is called. |
| 72 | - void ConfigureDeviceAsSerialPort(); | |
| 74 | + void ConfigureTermios(); | |
| 73 | 75 | |
| 74 | 76 | //! @brief Closes the COM port. |
| 75 | 77 | void Close(); | ... | ... |
src/SerialPort.cpp
| ... | ... | @@ -41,37 +41,13 @@ namespace CppLinuxSerial { |
| 41 | 41 | void SerialPort::SetDevice(const std::string& device) |
| 42 | 42 | { |
| 43 | 43 | device_ = device; |
| 44 | - ConfigureDeviceAsSerialPort(); | |
| 44 | + ConfigureTermios(); | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 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 | 49 | baudRate_ = baudRate; |
| 50 | + ConfigureTermios(); | |
| 75 | 51 | } |
| 76 | 52 | |
| 77 | 53 | void SerialPort::Open() |
| ... | ... | @@ -102,7 +78,7 @@ namespace CppLinuxSerial { |
| 102 | 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 | 83 | std::cout << "COM port opened successfully." << std::endl; |
| 108 | 84 | |
| ... | ... | @@ -120,45 +96,13 @@ namespace CppLinuxSerial { |
| 120 | 96 | this->SetTermios(settings); |
| 121 | 97 | } |
| 122 | 98 | |
| 123 | - void SerialPort::ConfigureDeviceAsSerialPort() | |
| 99 | + void SerialPort::ConfigureTermios() | |
| 124 | 100 | { |
| 125 | 101 | std::cout << "Configuring COM port \"" << device_ << "\"." << std::endl; |
| 126 | 102 | |
| 127 | 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 | 107 | //================= (.c_cflag) ===============// |
| 164 | 108 | |
| ... | ... | @@ -170,6 +114,32 @@ namespace CppLinuxSerial { |
| 170 | 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 | 143 | //===================== (.c_oflag) =================// |
| 174 | 144 | |
| 175 | 145 | tty.c_oflag = 0; // No remapping, no delays |
| ... | ... | @@ -180,7 +150,7 @@ namespace CppLinuxSerial { |
| 180 | 150 | // c_cc[WMIN] sets the number of characters to block (wait) for when read() is called. |
| 181 | 151 | // Set to 0 if you don't want read to block. Only meaningful when port set to non-canonical mode |
| 182 | 152 | //tty.c_cc[VMIN] = 1; |
| 183 | - this->SetNumCharsToWait(1); | |
| 153 | + SetNumCharsToWait(1); | |
| 184 | 154 | |
| 185 | 155 | // c_cc[VTIME] sets the inter-character timer, in units of 0.1s. |
| 186 | 156 | // Only meaningful when port is set to non-canonical mode |
| ... | ... | @@ -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 | 193 | // Get current termios struct |
| 225 | - termios myTermios = this->GetTermios(); | |
| 194 | + termios myTermios = GetTermios(); | |
| 226 | 195 | |
| 227 | 196 | // Save the number of characters to wait for |
| 228 | 197 | // to the control register |
| 229 | 198 | myTermios.c_cc[VMIN] = numCharsToWait; |
| 230 | 199 | |
| 231 | 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 | 205 | if(fileDesc_ == 0) { |
| 238 | 206 | //this->sp->PrintError(SmartPrint::Ss() << ); |
| 239 | 207 | //return false; | ... | ... |
test/unit/BasicTests.cpp
| ... | ... | @@ -53,16 +53,43 @@ namespace { |
| 53 | 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 | 67 | TEST_F(BasicTests, CanOpen) { |
| 57 | - SerialPort serialPort0(device0_, BaudRate::b57600); | |
| 68 | + SerialPort serialPort0(device0_, BaudRate::B_57600); | |
| 58 | 69 | serialPort0.Open(); |
| 59 | 70 | } |
| 60 | 71 | |
| 61 | 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 | 90 | serialPort0.Open(); |
| 64 | 91 | |
| 65 | - SerialPort serialPort1(device1_, BaudRate::b57600); | |
| 92 | + SerialPort serialPort1(device1_, BaudRate::B_57600); | |
| 66 | 93 | serialPort1.Open(); |
| 67 | 94 | |
| 68 | 95 | serialPort0.Write("Hello"); | ... | ... |