Files
pip/libs/main/io_devices/piserial.h
2022-12-14 14:13:52 +03:00

381 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file piserial.h
* \ingroup IO
* \~\brief
* \~english Serial device
* \~russian Последовательный порт
*/
/*
PIP - Platform Independent Primitives
COM
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISERIAL_H
#define PISERIAL_H
#include "piiodevice.h"
#include "pitimer.h"
//! \ingroup IO
//! \~\brief
//! \~english Serial device.
//! \~russian Последовательный порт.
class PIP_EXPORT PISerial: public PIIODevice {
PIIODEVICE(PISerial, "ser");
public:
//! \~english Contructs an empty %PISerial
//! \~russian Создает пустой %PISerial
explicit PISerial();
virtual ~PISerial();
//! \~english Parameters of PISerial
//! \~russian Параметры PISerial
enum Parameters {
ParityControl /*! \~english Enable parity check and generate \~russian Включить генерацию и проверку контроля чётности */ = 0x1,
ParityOdd /*! \~english Parity is odd instead of even \~russian Нечётный контроль чётности вместо чётного */ = 0x2,
TwoStopBits /*! \~english Two stop bits instead of one \~russian Два стоповых бита вместо одного */ = 0x4
};
//! \~english Speed of PISerial
//! \~russian Скорость PISerial
enum Speed {
S50 /*! 50 baud */ = 50,
S75 /*! 75 baud */ = 75,
S110 /*! 110 baud */ = 110,
S300 /*! 300 baud */ = 300,
S600 /*! 600 baud */ = 600,
S1200 /*! 1200 baud */ = 1200,
S2400 /*! 2400 baud */ = 2400,
S4800 /*! 4800 baud */ = 4800,
S9600 /*! 9600 baud */ = 9600,
S14400 /*! 14400 baud */ = 14400,
S19200 /*! 19200 baud */ = 19200,
S38400 /*! 38400 baud */ = 38400,
S57600 /*! 57600 baud */ = 57600,
S115200 /*! 115200 baud */ = 115200,
S230400 /*! 230400 baud */ = 230400,
S460800 /*! 460800 baud */ = 460800,
S500000 /*! 500000 baud */ = 500000,
S576000 /*! 576000 baud */ = 576000,
S921600 /*! 921600 baud */ = 921600,
S1000000 /*! 1000000 baud */ = 1000000,
S1152000 /*! 1152000 baud */ = 1152000,
S1500000 /*! 1500000 baud */ = 1500000,
S2000000 /*! 2000000 baud */ = 2000000,
S2500000 /*! 2500000 baud */ = 2500000,
S3000000 /*! 3000000 baud */ = 3000000,
S3500000 /*! 3500000 baud */ = 3500000,
S4000000 /*! 4000000 baud */ = 4000000
};
//! \ingroup IO
//! \~\brief
//! \~english Information about serial device
//! \~russian Информация о последовательном устройстве
struct PIP_EXPORT DeviceInfo {
//! \~english Returns string representation of USB ID in format "xxxx:xxxx" (vID:pID)
//! \~russian Возвращает строковое представление USB ID в формате "xxxx:xxxx" (vID:pID)
PIString id() const;
//! \~english USB Vendor ID
//! \~russian USB Vendor ID
uint vID = 0;
//! \~english USB Product ID
//! \~russian USB Product ID
uint pID = 0;
//! \~english Path to device, e.g. "COM2" or "/dev/ttyUSB0"
//! \~russian Путь к устройству, например "COM2" или "/dev/ttyUSB0"
PIString path;
//! \~english Device description
//! \~russian Описание устройства
PIString description;
//! \~english Device manufacturer
//! \~russian Описание производителя
PIString manufacturer;
};
//! \~english Contructs %PISerial with device name "device", speed "speed" and parameters "params"
//! \~russian Создает %PISerial с именем устройства "device", скоростью "speed" и параметрами "params"
explicit PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
//! \~english Set both input and output speed to "speed"
//! \~russian Устанавливает скорости приема и передачи в "speed"
void setSpeed(PISerial::Speed speed) {
setProperty("outSpeed", (int)speed);
setProperty("inSpeed", (int)speed);
applySettings();
}
//! \~english Set output speed to "speed"
//! \~russian Устанавливает скорость передачи в "speed"
void setOutSpeed(PISerial::Speed speed) {
setProperty("outSpeed", (int)speed);
applySettings();
}
//! \~english Set input speed to "speed"
//! \~russian Устанавливает скорость приема в "speed"
void setInSpeed(PISerial::Speed speed) {
setProperty("inSpeed", (int)speed);
applySettings();
}
//! \~english Set device name to "dev"
//! \~russian Устанавливает имя устройства в "dev"
void setDevice(const PIString & dev) {
setPath(dev);
if (isOpened()) {
close();
open();
};
}
//! \~english Set parameters to "parameters_"
//! \~russian Устанавливает параметры в "parameters_"
void setParameters(PIFlags<PISerial::Parameters> parameters_) {
setProperty("parameters", (int)parameters_);
applySettings();
}
//! \~english Set parameter "parameter" to "on" state
//! \~russian Устанавливает параметр "parameter" в "on"
void setParameter(PISerial::Parameters parameter, bool on = true);
//! \~english Returns if parameter "parameter" is set
//! \~russian Возвращает установлен ли параметр "parameter"
bool isParameterSet(PISerial::Parameters parameter) const;
//! \~english Returns parameters
//! \~russian Возвращает параметры
PIFlags<PISerial::Parameters> parameters() const { return (PIFlags<Parameters>)(property("parameters").toInt()); }
//! \~english Set data bits count. Valid range is from 5 to 8, befault is 8
//! \~russian Устанавливает количество бит данных. Разрешены значения от 5 до 8, по умолчанию 8
void setDataBitsCount(int bits) {
setProperty("dataBitsCount", bits);
applySettings();
}
//! \~english Returns data bits count
//! \~russian Возвращает количество бит данных
int dataBitsCount() const { return property("dataBitsCount").toInt(); }
//! \~english Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS)
//! \~russian Устанавливает пин с номером "number" в логический уровень "on". Разрешены номера 4 (DTR) и 7 (RTS)
bool setPin(int number, bool on);
//! \~english Returns pin number "number" logic level. Valid numbers range is from 1 to 9
//! \~russian Возвращает логический уровень пина с номером "number". Разрешены номера от 1 до 9
bool isPin(int number) const;
bool setLE(bool on); // useless function, just formally
bool setDTR(bool on);
bool setRTS(bool on);
bool setCTS(bool on); // useless function, just formally
bool setST(bool on); // useless function, just formally
bool setSR(bool on); // useless function, just formally
bool setCAR(bool on); // useless function, just formally
bool setRNG(bool on); // useless function, just formally
bool setDSR(bool on); // useless function, just formally
bool isLE() const;
bool isDTR() const;
bool isRTS() const;
bool isCTS() const;
bool isST() const;
bool isSR() const;
bool isCAR() const;
bool isRNG() const;
bool isDSR() const;
//! \~english Switch transmission line in break
//! \~russian Переключает состояние передачи в break
bool setBreak(bool enabled);
void setVTime(int t) {
vtime = t;
applySettings();
}
//! \~english Returns device name
//! \~russian Возвращает имя устройства
PIString device() const { return path(); }
//! \~english Returns output speed
//! \~russian Возвращает скорость передачи
PISerial::Speed outSpeed() const { return (PISerial::Speed)(property("outSpeed").toInt()); }
//! \~english Returns input speed
//! \~russian Возвращает скорость приема
PISerial::Speed inSpeed() const { return (PISerial::Speed)(property("inSpeed").toInt()); }
int VTime() const { return vtime; }
//! \~english Discard all buffered input and output data
//! \~russian Откидывает все буферизированные данные для передачи и приема
virtual void flush() override;
int read(void * read_to, int max_size) { return readDevice(read_to, max_size); }
//! \~english Read from device no more "max_size" bytes into "read_to" with "timeout_ms" timeout
//! \~russian Читает из устройства не более "max_size" байт в "read_to" с таймаутом "timeout_ms"
bool read(void * read_to, int max_size, double timeout_ms);
//! \~english Read from device for "timeout_ms" timeout or for "size" bytes
//! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт
PIString readString(int size = -1, double timeout_ms = 1000.);
//! \~english Read from device for "timeout_ms" timeout or for "size" bytes
//! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт
PIByteArray readData(int size = -1, double timeout_ms = 1000.);
//! \~english Write to device data "data" with maximum size "size". Returns if sended bytes count = "size"
//! \~russian Пишет в порт не более "size" байт данных "data". Возвращает если количество записанных байт = "size"
bool send(const void * data, int size);
//! \~english Write to device byte array "data". Returns if sended bytes count = size of "data"
//! \~russian Пишет в порт байтовый массив "data". Возвращает если количество записанных байт = размер "data"
bool send(const PIByteArray & data) { return send(data.data(), data.size_s()); }
void interrupt() override;
//! \~english Returns all available speeds for serial devices
//! \~russian Возвращает все возможные скорости для устройств
static PIVector<int> availableSpeeds();
//! \~english Returns all available system devices path. If "test" each device will be tried to open
//! \~russian Возвращает пути всех доступных устройств в системе. Если "test", то каждое устройство будет опробовано на открытие
static PIStringList availableDevices(bool test = false);
//! \~english Returns all available system devices. If "test" each device will be tried to open
//! \~russian Возвращает все доступные устройства в системе. Если "test", то каждое устройство будет опробовано на открытие
static PIVector<DeviceInfo> availableDevicesInfo(bool test = false);
//! \ioparams
//! \{
#ifdef DOXYGEN
//! \~english device, default ""
//! \~russian устройство, по умолчанию ""
string device;
//! \~english input/output speed, default 115200
//! \~russian скорость чтения/записи, по умолчанию 115200
int speed;
//! \~english dataBitsCount, default 8
//! \~russian количесво бит данных, по умолчанию 8
int dataBitsCount;
//! \~english parityControl, default false
//! \~russian контроль четности, по умолчанию false
bool parityControl;
//! \~english parityOdd, default false
//! \~russian нечётный контроль четности, по умолчанию false
bool parityOdd;
//! \~english twoStopBits, default false
//! \~russian два стоповых бита, по умолчанию false
bool twoStopBits;
#endif
//! \}
protected:
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
bool configureDevice(const void * e_main, const void * e_parent = 0) override;
void optionsChanged() override;
void threadedReadBufferSizeChanged() override;
//! \~english Basic read function
//! \~russian Базовое чтение
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Sequential; }
//! Executes when any read function was successful. Default implementation does nothing
virtual void received(const void * data, int size) { ; }
void construct();
void applySettings();
void setTimeouts();
int convertSpeed(PISerial::Speed speed);
bool setBit(int bit, bool on, const PIString & bname);
bool isBit(int bit, const PIString & bname) const;
bool openDevice() override;
bool closeDevice() override;
PRIVATE_DECLARATION(PIP_EXPORT)
int fd = -1, vtime = 10;
std::atomic_bool sending;
PITimeMeasurer tm_;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator<<(PICout s, const PISerial::DeviceInfo & v) {
s << v.path << " (" << v.id() << ", \"" << v.manufacturer << "\", \"" << v.description << "\")";
return s;
}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator==(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {
return v0.path == v1.path;
}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator!=(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {
return v0.path != v1.path;
}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PISerial::DeviceInfo) {
s << v.vID << v.pID << v.path << v.description << v.manufacturer;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PISerial::DeviceInfo) {
s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer;
return s;
}
#endif // PISERIAL_H