381 lines
15 KiB
C++
381 lines
15 KiB
C++
/*! \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
|