|
| 1 | +/// |
| 2 | +/// \file SerialPort.hpp |
| 3 | +/// \author Geoffrey Hunter <gbmhunter@gmail.com> (www.mbedded.ninja) |
| 4 | +/// \created 2014-01-07 |
| 5 | +/// \last-modified 2023-02-13 |
| 6 | +/// \brief The main serial port class. |
| 7 | +/// \details |
| 8 | +/// See README.rst in repo root dir for more info. |
| 9 | + |
| 10 | +// Header guard |
| 11 | +#ifndef SERIAL_PORT_SERIAL_PORT_H |
| 12 | +#define SERIAL_PORT_SERIAL_PORT_H |
| 13 | + |
| 14 | +// System headers |
| 15 | +#include <string> |
| 16 | +#include <fstream> // For file I/O (reading/writing to COM port) |
| 17 | +#include <sstream> |
| 18 | +// #include <termios.h> // POSIX terminal control definitions (struct termios) |
| 19 | +// #include <asm/termios.h> // Terminal control definitions (struct termios) |
| 20 | +#include <vector> |
| 21 | +#include <asm/ioctls.h> |
| 22 | +#include <asm/termbits.h> |
| 23 | + |
| 24 | +// User headers |
| 25 | +#include "Exception.hpp" |
| 26 | + |
| 27 | +namespace mn { |
| 28 | + namespace CppLinuxSerial { |
| 29 | + |
| 30 | + /// \brief Represents the baud rate "types" that can be used with the serial port. STANDARD represents all |
| 31 | + /// the standard baud rates as provided by UNIX, CUSTOM represents a baud rate defined by an arbitray integer. |
| 32 | + enum class BaudRateType { |
| 33 | + STANDARD, |
| 34 | + CUSTOM, |
| 35 | + }; |
| 36 | + |
| 37 | + /// \brief Strongly-typed enumeration of baud rates for use with the SerialPort class |
| 38 | + /// \details Specifies all the same baud rates as UNIX, as well as B_CUSTOM to specify your |
| 39 | + /// own. See https://linux.die.net/man/3/cfsetispeed for list of supported UNIX baud rates. |
| 40 | + enum class BaudRate { |
| 41 | + B_0, |
| 42 | + B_50, |
| 43 | + B_75, |
| 44 | + B_110, |
| 45 | + B_134, |
| 46 | + B_150, |
| 47 | + B_200, |
| 48 | + B_300, |
| 49 | + B_600, |
| 50 | + B_1200, |
| 51 | + B_1800, |
| 52 | + B_2400, |
| 53 | + B_4800, |
| 54 | + B_9600, |
| 55 | + B_19200, |
| 56 | + B_38400, |
| 57 | + B_57600, |
| 58 | + B_115200, |
| 59 | + B_230400, |
| 60 | + B_460800, |
| 61 | + B_CUSTOM, // Placeholder |
| 62 | + }; |
| 63 | + |
| 64 | + /// \brief Enumeration of all the valid num. of data bits. Must align with the options |
| 65 | + /// provided in termbits.h, i.e. CS5, CS6, CS7 and CS8. |
| 66 | + enum class NumDataBits { |
| 67 | + FIVE, |
| 68 | + SIX, |
| 69 | + SEVEN, |
| 70 | + EIGHT, |
| 71 | + }; |
| 72 | + |
| 73 | + enum class Parity { |
| 74 | + NONE, |
| 75 | + EVEN, |
| 76 | + ODD, |
| 77 | + }; |
| 78 | + |
| 79 | + enum class NumStopBits { |
| 80 | + ONE, |
| 81 | + TWO, |
| 82 | + }; |
| 83 | + |
| 84 | + /// \brief All the possible options for setting the hardware flow control. |
| 85 | + enum class HardwareFlowControl { |
| 86 | + OFF, |
| 87 | + ON, |
| 88 | + }; |
| 89 | + |
| 90 | + /// \brief All the possible options for setting the software flow control. |
| 91 | + enum class SoftwareFlowControl { |
| 92 | + OFF, |
| 93 | + ON, |
| 94 | + }; |
| 95 | + |
| 96 | + /// \brief Represents the state of the serial port. |
| 97 | + enum class State { |
| 98 | + CLOSED, |
| 99 | + OPEN, |
| 100 | + }; |
| 101 | + |
| 102 | + /// \brief SerialPort object is used to perform rx/tx serial communication. |
| 103 | + class SerialPort { |
| 104 | + |
| 105 | + public: |
| 106 | + /// \brief Default constructor. You must specify at least the device before calling Open(). |
| 107 | + SerialPort(); |
| 108 | + |
| 109 | + /// \brief Constructor that sets up serial port with the basic (required) parameters. |
| 110 | + SerialPort(const std::string &device, BaudRate baudRate); |
| 111 | + |
| 112 | + /// \brief Constructor that sets up serial port and allows the user to specify all the common parameters. |
| 113 | + SerialPort(const std::string &device, BaudRate baudRate, NumDataBits numDataBits, Parity parity, NumStopBits numStopBits); |
| 114 | + |
| 115 | + /// \brief Constructor that sets up serial port and allows the user to specify all the common parameters and flow control. |
| 116 | + SerialPort(const std::string &device, BaudRate baudRate, NumDataBits numDataBits, Parity parity, |
| 117 | + NumStopBits numStopBits, HardwareFlowControl hardwareFlowControl, SoftwareFlowControl softwareFlowControl); |
| 118 | + |
| 119 | + /// \brief Constructor that sets up serial port with the basic parameters, and a custom baud rate. |
| 120 | + SerialPort(const std::string &device, speed_t baudRate); |
| 121 | + |
| 122 | + /// \brief Destructor. Closes serial port if still open. |
| 123 | + virtual ~SerialPort(); |
| 124 | + |
| 125 | + /// \brief Sets the device to use for serial port communications. |
| 126 | + /// \details Method can be called when serial port is in any state. |
| 127 | + void SetDevice(const std::string &device); |
| 128 | + |
| 129 | + /// \brief Call this to set a standard baud rate. |
| 130 | + void SetBaudRate(BaudRate baudRate); |
| 131 | + |
| 132 | + /// \brief Call this to set a custom baud rate. |
| 133 | + void SetBaudRate(speed_t baudRate); |
| 134 | + |
| 135 | + /// \brief Call this to set the num. of data bits. |
| 136 | + void SetNumDataBits(NumDataBits numDataBits); |
| 137 | + |
| 138 | + /// \brief Call this to set the parity. |
| 139 | + void SetParity(Parity parity); |
| 140 | + |
| 141 | + /// \brief Call this to set the number of stop bits. |
| 142 | + void SetNumStopBits(NumStopBits numStopBits); |
| 143 | + |
| 144 | + /// \brief Sets the read timeout (in milliseconds)/blocking mode. |
| 145 | + /// \details Only call when state != OPEN. This method manupulates VMIN and VTIME. |
| 146 | + /// \param timeout_ms Set to -1 to infinite timeout, 0 to return immediately with any data (non |
| 147 | + /// blocking, or >0 to wait for data for a specified number of milliseconds). Timeout will |
| 148 | + /// be rounded to the nearest 100ms (a Linux API restriction). Maximum value limited to |
| 149 | + /// 25500ms (another Linux API restriction). |
| 150 | + void SetTimeout(int32_t timeout_ms); |
| 151 | + |
| 152 | + /// \brief Enables/disables echo. |
| 153 | + /// \param value Pass in true to enable echo, false to disable echo. |
| 154 | + void SetEcho(bool value); |
| 155 | + |
| 156 | + /// \brief Opens the COM port for use. |
| 157 | + /// \throws CppLinuxSerial::Exception if device cannot be opened. |
| 158 | + /// \note Must call this before you can configure the COM port. |
| 159 | + void Open(); |
| 160 | + |
| 161 | + /// \brief Closes the COM port. |
| 162 | + void Close(); |
| 163 | + |
| 164 | + /// \brief Sends a text message over the com port. |
| 165 | + /// \param data The data that will be written to the COM port. |
| 166 | + /// \throws CppLinuxSerial::Exception if state != OPEN. |
| 167 | + void Write(const std::string& data); |
| 168 | + |
| 169 | + /// \brief Sends a binary message over the com port. |
| 170 | + /// \param data The data that will be written to the COM port. |
| 171 | + /// \throws CppLinuxSerial::Exception if state != OPEN. |
| 172 | + void WriteBinary(const std::vector<uint8_t>& data); |
| 173 | + |
| 174 | + /// \brief Use to read text from the COM port. Blocking nature depends on SetTimeout(). |
| 175 | + /// \param data The read characters from the COM port will be appended to this string. |
| 176 | + /// \note Use ReadBinary() if you want to interpret received data as binary. |
| 177 | + /// \throws |
| 178 | + /// CppLinuxSerial::Exception if state != OPEN. |
| 179 | + /// std::system_error() if device has been disconnected. |
| 180 | + void Read(std::string& data); |
| 181 | + |
| 182 | + /// \brief Use to read binary data from the COM port. Blocking nature depends on SetTimeout(). |
| 183 | + /// \param data The read bytes from the COM port will be appended to this vector. |
| 184 | + /// \note Use Read() if you want to interpret received data as a string. |
| 185 | + /// \throws CppLinuxSerial::Exception if state != OPEN. |
| 186 | + /// std::system_error() if device has been disconnected. |
| 187 | + void ReadBinary(std::vector<uint8_t>& data); |
| 188 | + |
| 189 | + /// \brief Use to get number of bytes available in receive buffer. |
| 190 | + /// \returns The number of bytes available in the receive buffer (ready to be read). |
| 191 | + /// \throws CppLinuxSerial::Exception if state != OPEN. |
| 192 | + int32_t Available(); |
| 193 | + |
| 194 | + /// \brief Use to get the state of the serial port |
| 195 | + /// \returns The state of the serial port |
| 196 | + State GetState(); |
| 197 | + |
| 198 | + private: |
| 199 | + |
| 200 | + /// \brief Configures the tty device as a serial port. |
| 201 | + /// \warning Device must be open (valid file descriptor) when this is called. |
| 202 | + void ConfigureTermios(); |
| 203 | + |
| 204 | + // void SetTermios(termios myTermios); |
| 205 | + |
| 206 | + /// \brief Returns a populated termios2 structure for the serial port pointed to by the file descriptor. |
| 207 | + termios2 GetTermios2(); |
| 208 | + |
| 209 | + /// \brief Assigns the provided tty settings to the serial port pointed to by the file descriptor. |
| 210 | + void SetTermios2(termios2 tty); |
| 211 | + |
| 212 | + /// \brief Keeps track of the serial port's state. |
| 213 | + State state_; |
| 214 | + |
| 215 | + /// \brief The file path to the serial port device (e.g. "/dev/ttyUSB0"). |
| 216 | + std::string device_; |
| 217 | + |
| 218 | + /// \brief The type of baud rate that the user has specified. |
| 219 | + BaudRateType baudRateType_; |
| 220 | + |
| 221 | + /// \brief The current baud rate if baudRateType_ == STANDARD. |
| 222 | + BaudRate baudRateStandard_; |
| 223 | + |
| 224 | + /// \brief The current baud rate if baudRateType_ == CUSTOM. |
| 225 | + speed_t baudRateCustom_; |
| 226 | + |
| 227 | + /// \brief The num. of data bits. Defaults to 8 (most common). |
| 228 | + NumDataBits numDataBits_ = NumDataBits::EIGHT; |
| 229 | + |
| 230 | + /// \brief The parity. Defaults to none (most common). |
| 231 | + Parity parity_ = Parity::NONE; |
| 232 | + |
| 233 | + /// \brief The num. of stop bits. Defaults to 1 (most common). |
| 234 | + NumStopBits numStopBits_ = NumStopBits::ONE; |
| 235 | + |
| 236 | + /// \brief The hardware flow control setting. Defaults to OFF (most common). |
| 237 | + HardwareFlowControl hardwareFlowControl_ = HardwareFlowControl::OFF; |
| 238 | + |
| 239 | + /// \brief The software flow control setting. Defaults to OFF (most common). |
| 240 | + SoftwareFlowControl softwareFlowControl_ = SoftwareFlowControl::OFF; |
| 241 | + |
| 242 | + /// \brief The file descriptor for the open file. This gets written to when Open() is called. |
| 243 | + int fileDesc_; |
| 244 | + |
| 245 | + bool echo_; |
| 246 | + |
| 247 | + int32_t timeout_ms_; |
| 248 | + |
| 249 | + std::vector<char> readBuffer_; |
| 250 | + unsigned char readBufferSize_B_; |
| 251 | + |
| 252 | + static constexpr BaudRate defaultBaudRate_ = BaudRate::B_57600; |
| 253 | + static constexpr int32_t defaultTimeout_ms_ = -1; |
| 254 | + static constexpr unsigned char defaultReadBufferSize_B_ = 255; |
| 255 | + |
| 256 | + }; |
| 257 | + |
| 258 | + } // namespace CppLinuxSerial |
| 259 | +} // namespace mn |
| 260 | + |
| 261 | +#endif // #ifndef SERIAL_PORT_SERIAL_PORT_H |
0 commit comments