summaryrefslogtreecommitdiff
path: root/src/voltronic/serial_device.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/voltronic/serial_device.cc')
-rw-r--r--src/voltronic/serial_device.cc160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/voltronic/serial_device.cc b/src/voltronic/serial_device.cc
new file mode 100644
index 0000000..d8b7c98
--- /dev/null
+++ b/src/voltronic/serial_device.cc
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include <stdexcept>
+#include <algorithm>
+#include <libserialport.h>
+
+#include "device.h"
+#include "exceptions.h"
+#include "../logging.h"
+
+namespace voltronic {
+
+const char* SerialDevice::DEVICE_NAME = "/dev/ttyUSB0";
+
+SerialDevice::SerialDevice(std::string& name,
+ SerialBaudRate baudRate,
+ SerialDataBits dataBits,
+ SerialStopBits stopBits,
+ SerialParity parity)
+ : port_(nullptr)
+ , name_(name)
+ , baudRate_(baudRate)
+ , dataBits_(dataBits)
+ , stopBits_(stopBits)
+ , parity_(parity)
+{
+ if (sp_get_port_by_name(name_.c_str(), &port_) != SP_OK)
+ throw DeviceError("failed to get port by name");
+
+ if (sp_open(port_, SP_MODE_READ_WRITE) != SP_OK)
+ throw DeviceError("failed to open device");
+
+ SerialPortConfiguration config(*this);
+ config.setConfiguration(baudRate_, dataBits_, stopBits_, parity_);
+
+ sp_flush(port_, SP_BUF_BOTH);
+}
+
+SerialDevice::~SerialDevice() {
+ if (port_ != nullptr) {
+ if (sp_close(port_) == SP_OK)
+ sp_free_port(port_);
+ }
+}
+
+unsigned int SerialDevice::getTimeout() {
+ return !timeout_
+ // to wait indefinitely if no timeout set
+ ? 0
+ // if getTimeLeft() suddently returns 0, pass 1,
+ // otherwise libserialport will treat it like 'wait indefinitely'
+ : std::max(static_cast<unsigned>(getTimeLeft()), static_cast<unsigned>(1));
+}
+
+size_t SerialDevice::read(u8* buf, size_t bufSize) {
+ if (verbose_)
+ myerr << "reading...";
+ return sp_blocking_read_next(port_, buf, bufSize, getTimeout());
+}
+
+size_t SerialDevice::write(const u8* data, size_t dataSize) {
+ return sp_blocking_write(port_, data, dataSize, getTimeout());
+}
+
+
+/**
+ * Serial port configuration
+ */
+
+SerialPortConfiguration::SerialPortConfiguration(SerialDevice& device)
+ : config_(nullptr), device_(device)
+{
+ if (sp_new_config(&config_) != SP_OK)
+ throw DeviceError("failed to allocate port configuration");
+
+ if (sp_get_config(device.getPort(), config_) != SP_OK)
+ throw DeviceError("failed to get current port configuration");
+}
+
+SerialPortConfiguration::~SerialPortConfiguration() {
+ if (config_ != nullptr)
+ sp_free_config(config_);
+}
+
+void SerialPortConfiguration::setConfiguration(SerialBaudRate baudRate,
+ SerialDataBits dataBits,
+ SerialStopBits stopBits,
+ SerialParity parity) {
+ if (sp_set_config_baudrate(config_, static_cast<int>(baudRate)) != SP_OK)
+ throw DeviceError("failed to set baud rate");
+
+ if (sp_set_config_bits(config_, static_cast<int>(dataBits)) != SP_OK)
+ throw DeviceError("failed to set data bits");
+
+ if (sp_set_config_stopbits(config_, static_cast<int>(stopBits)) != SP_OK)
+ throw DeviceError("failed to set stop bits");
+
+ if (sp_set_config_parity(config_, static_cast<enum sp_parity>(parity)) != SP_OK)
+ throw DeviceError("failed to set parity");
+
+ if (sp_set_config(device_.getPort(), config_) != SP_OK)
+ throw DeviceError("failed to set port configuration");
+}
+
+bool is_serial_baud_rate_valid(SerialBaudRate baudRate) {
+ switch (baudRate) {
+ case 110:
+ case 300:
+ case 1200:
+ case 2400:
+ case 4800:
+ case 9600:
+ case 19200:
+ case 38400:
+ case 57600:
+ case 115200:
+ return true;
+
+ default: break;
+ }
+ return false;
+}
+
+bool is_serial_data_bits_valid(SerialDataBits dataBits) {
+ switch (dataBits) {
+ case SerialDataBits::Five:
+ case SerialDataBits::Six:
+ case SerialDataBits::Seven:
+ case SerialDataBits::Eight:
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+bool is_serial_stop_bits_valid(SerialStopBits stopBits) {
+ switch (stopBits) {
+ case SerialStopBits::One:
+ case SerialStopBits::OneAndHalf:
+ case SerialStopBits::Two:
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+bool is_serial_parity_valid(SerialParity parity) {
+ switch (parity) {
+ case SerialParity::None:
+ case SerialParity::Odd:
+ case SerialParity::Even:
+ case SerialParity::Mark:
+ case SerialParity::Space:
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+} \ No newline at end of file