diff --git a/src/Uart.cc b/src/Uart.cc new file mode 100644 index 0000000..17941ef --- /dev/null +++ b/src/Uart.cc @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Uart.h" + +Uart::Uart(const char* name) +{ + assert(name != nullptr); + serial_device = open(name, O_RDWR); + if (serial_device < 0) + { + printf("unable to open serial port\r\n"); + exit(1); + } + + // Create new termios struct, we call it 'tty' for convention + // No need for "= {0}" at the end as we'll immediately write the existing + // config to this struct + struct termios tty; + + // Read in existing settings, and handle any error + // NOTE: This is important! POSIX states that the struct passed to tcsetattr() + // must have been initialized with a call to tcgetattr() overwise behaviour + // is undefined + if (tcgetattr(serial_device, &tty) != 0) + { + printf("Error %i from tcgetattr: %s\n", errno, strerror(errno)); + close(serial_device); + exit(2); + } + + tty.c_cflag |= PARENB; // Clear parity bit, disabling parity (most common) + tty.c_cflag &= ~PARODD; + tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common) + + tty.c_cflag &= ~CSIZE; // First clear all the size bits + tty.c_cflag |= CS8; // 8 bits per byte (most common) + + tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common) + tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) + + tty.c_lflag &= ~ICANON; + tty.c_lflag &= ~ECHO; // Disable echo + tty.c_lflag &= ~ECHOE; // Disable erasure + tty.c_lflag &= ~ECHONL; // Disable new-line echo + tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP + + tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes + + tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) + tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed + + tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received. + tty.c_cc[VMIN] = 0; + + cfsetispeed(&tty, B115200); + cfsetospeed(&tty, B115200); + + // Save tty settings, also checking for error + if (tcsetattr(serial_device, TCSANOW, &tty) != 0) + { + printf("Error %i from tcsetattr: %s\n", errno, strerror(errno)); + close(serial_device); + exit(3); + } +} + +Uart::~Uart() +{ + close(serial_device); +} + +int Uart::transmit(const unsigned char *buffer, size_t len) +{ + return write(serial_device, buffer, len); +} + +int Uart::receive(unsigned char *buffer, size_t len) +{ + return read(serial_device, buffer, len); +} diff --git a/src/Uart.h b/src/Uart.h new file mode 100644 index 0000000..5356f3b --- /dev/null +++ b/src/Uart.h @@ -0,0 +1,19 @@ +#ifndef UART_H +#define UART_H + +#include + +class Uart +{ +public: + Uart(const char *name); + ~Uart(); + + int transmit(const unsigned char *buffer, size_t len); + int receive(unsigned char *buffer, size_t len); + +private: + int serial_device = 0; +}; + +#endif