224 lines
8.6 KiB
C++
224 lines
8.6 KiB
C++
/*
|
||
* SlipCommunication.h
|
||
*
|
||
* Created on: 31 марта 2017 г.
|
||
* Author: titov
|
||
*/
|
||
|
||
#ifndef SOURCES_DRIVERS_SLIPCOMMUNICATION_H_
|
||
#define SOURCES_DRIVERS_SLIPCOMMUNICATION_H_
|
||
|
||
#include "../driver/IDataLink.hh"
|
||
#include "../driver/ISlipCommunication.hh"
|
||
|
||
#include "../peripheral/IUartPort.hh"
|
||
#include "../driver/IDiscreteOutput.hh"
|
||
|
||
#include "../systemic/IProcess.hh"
|
||
#include "../systemic/Timer.hh"
|
||
|
||
#include "../common/CircularBuffer.hpp"
|
||
#include "../common/Crc.hh"
|
||
|
||
#include <cstddef>
|
||
#include <stdint.h>
|
||
|
||
namespace driver {
|
||
|
||
//todo: depricated!!!!
|
||
class SlipCommunication : public ISlipCommunication, public systemic::IProcess {
|
||
private:
|
||
//!Структура описания режима приема байт.
|
||
struct TReceiveMode {
|
||
enum ID {
|
||
HEAD = 0, //!<Прием заголовка.
|
||
DATA = 1, //!<Прием данных.
|
||
CRC16 = 2, //!<Прием контрольной суммы.
|
||
STOP = 3, //!<Ожидание конца пакета.
|
||
SLEEP = 4 //!<Пропуск всех данных.
|
||
};
|
||
};
|
||
//!Структура описывает коды слип-пакета.
|
||
struct TSlipDecode {
|
||
enum BYTECODE {
|
||
DB = 0x00DB,
|
||
DC = 0x00DC,
|
||
DD = 0x00DD,
|
||
C0 = 0x00C0
|
||
};
|
||
|
||
static const unsigned short END = 0xC0C0;
|
||
static const unsigned short ERROR = 0xFFC0;
|
||
static const unsigned short NOTBYTE = 0xDBDB;
|
||
};
|
||
|
||
static const int head_size = 5; //!<Размер буфера для заголовка.
|
||
|
||
//!Структура описывает данные заголовка пакета.
|
||
struct THead {
|
||
unsigned short packet_size; //! Слово размера пакета.
|
||
unsigned short packet_id; //! Слово идентификатор пакета.
|
||
unsigned short hw_address; //! Адресуемый абонент.
|
||
|
||
THead() : packet_size(0), packet_id(0), hw_address(0) {}
|
||
void deserialize(char (& buff)[head_size]);
|
||
};
|
||
|
||
//!Максимальный размер данных в байтах для входящего пакета.
|
||
int max_datasize;
|
||
|
||
//!Адрес на шине.
|
||
unsigned short hw_address;
|
||
|
||
SlipCommunication & operator=(const SlipCommunication &);
|
||
SlipCommunication(SlipCommunication &);
|
||
|
||
bool packet_start = false;
|
||
|
||
private:
|
||
static const std::size_t rx_buffer = 128;
|
||
|
||
peripheral::IUartPort & bus; //!<Шина передачи данных.
|
||
driver::IDiscreteOutput & de; //!<Пин выбора направления передачи данных.
|
||
|
||
systemic::Timer timeout; //!<Таймаут для принятия байт
|
||
|
||
unsigned int error_count;
|
||
const unsigned int max_error;
|
||
bool bus_enable;
|
||
|
||
//TODO: Древний црц.
|
||
Crc<16, 0x1021, 0xFFFF, false, false, 0> crc16rec; //!<Контрольная сумма для принятых данных
|
||
Crc<16, 0x1021, 0xFFFF, false, false, 0> crc16send; //!<Контрльная сумма для отправляемых данных
|
||
|
||
//!Количество полученных пакетов.
|
||
int incoming_packet;
|
||
//!Режим приема.
|
||
TReceiveMode::ID receive_mode;
|
||
//!Байт-заменитель принят.
|
||
bool byte_db_recived;
|
||
//!Данные готовы.
|
||
bool data_ready;
|
||
|
||
//Дешифрованые заголовок и контрольная сумма.
|
||
THead packet_head; //!<Заголовок.
|
||
unsigned int packet_crc16; //!<Контрольная сумма данных.
|
||
|
||
//Буфер заголовка.
|
||
int count_head_byte; //!<Количество принятых байт заголовка.
|
||
char head_buff[head_size]; //!<Буфер для заголовка.
|
||
|
||
//Буфер данных.
|
||
int count_data_byte; //!<Количество принятых байт данных.
|
||
|
||
//TODO: Циркулярный буфер вместе с объектом.
|
||
int totalRecLength; //!<Количество оставшихся не считанных байт.
|
||
CircularBuffer<rx_buffer> receiveBuffer; //!<Буфер принимаемых данных
|
||
|
||
//Буфер контрольной суммы.
|
||
int count_crc16_byte; //!<Количество принятых байт контрольной суммы.
|
||
static const int crc16_size = 2; //!<Размер буфера для контрольной суммы.
|
||
char crc16_buff[crc16_size]; //!<Буфер для контрольной суммы.
|
||
|
||
private:
|
||
void recieve_restart(); //!<Переход в ожидание нового сообщения.
|
||
void create_packet(); //!<Формирование пакета.
|
||
|
||
bool packet_end() const; //!Признак окончания приема пакета. \return Данные собраны.
|
||
bool data_collection(char byte); //!Сбор входящих байт для пакета. \return Данные собраны.
|
||
|
||
/*!\brief Функция декодирования slip протокола.
|
||
* \return Декодированный байт или специальное состояние.*/
|
||
unsigned short slip_decode(char byte);
|
||
|
||
/*!\brief Обработка нового принятого байта.
|
||
* \return Признак завершения приема текущего пакета.*/
|
||
bool byte_processing(char byte);
|
||
|
||
/*!\brief Функция кодирования в slip и отправки байта.
|
||
* \return Признак успешной отправки байта. */
|
||
bool slip_send(char byte);
|
||
|
||
/*!\brief Функция отправки слова без подсчета CRC16.
|
||
* \return Признак успешной отправки байта.*/
|
||
bool send_word_without_crc(unsigned short word);
|
||
/*!\brief Функция отправки байта c подсчетом CRC16.
|
||
* \return Признак успешной отправки байта.*/
|
||
bool send_byte_with_crc(unsigned char byte);
|
||
/*!\brief Функция отправки слова c подсчетом CRC16.
|
||
* \return Признак успешной отправки слова.*/
|
||
bool send_word_with_crc(unsigned short word);
|
||
/*!\brief Функция получения очередного слова из буфера.
|
||
* \return Слово из буфера.*/
|
||
unsigned short recieve_word();
|
||
|
||
/*!\brief Функция получения очередного слова из буфера.
|
||
* \return Слово из буфера.*/
|
||
char recieve_byte();
|
||
|
||
|
||
void deserialize_crc16(); //!<Формирование контрольной суммы из принятых байт.
|
||
|
||
/*!\brief Функция приема данных, потоком.
|
||
* \return Признак приема данных.*/
|
||
bool recieve_data(char * data, short length);
|
||
|
||
/*!\brief Функция отправления пакета, целиком.
|
||
* \return Признак отправки пакета.*/
|
||
bool send_packet(unsigned short id, const char * data, short length);
|
||
|
||
/*!\brief Функция сброса отправляемых байт. */
|
||
void send_reset();
|
||
|
||
/*!\brief Функция отправления байта, потоком.
|
||
* \param[in] byte - байт для отправки.
|
||
* \param[in] first_data - признак отправки первой партии данных, в случае если отправляется пакет без заголовка.
|
||
* \return Признак отправки данных. */
|
||
bool send_byte(unsigned short byte, bool first_data = false);
|
||
public:
|
||
|
||
std::pair<bool, unsigned short> isPacketAvailable() const;
|
||
std::size_t packetSize() const { return packet_head.packet_size; }
|
||
|
||
/*!\brief Функция отправления заголовочных данных.
|
||
* \param[in] id Тип сообщения.
|
||
* \param[in] size Размер поля данных, в байт.
|
||
* \return Признак отправки данных.*/
|
||
bool sendHead(unsigned short id, unsigned short size) noexcept;
|
||
|
||
bool send( const char * data, std::size_t size );
|
||
bool receive( char * data, std::size_t size );
|
||
|
||
/*!\brief Функция сброса принятых данных.
|
||
**/
|
||
void recieveReset();
|
||
|
||
/*!\brief Функция отправления конца пакета.
|
||
* \return Признак отправки данных.*/
|
||
bool sendEnd() noexcept;
|
||
|
||
bool isPacketSent() const;
|
||
|
||
std::size_t transmitBuffCapacity() const { return ( bus.transmitBuffCapacity() / 2 ) - 5 - 3; }
|
||
std::size_t receiveBuffCapacity() const { return rx_buffer; }
|
||
|
||
|
||
public:
|
||
SlipCommunication(
|
||
peripheral::IUartPort & bus,
|
||
driver::IDiscreteOutput & de = driver::getDummyOutput()
|
||
);
|
||
|
||
virtual ~SlipCommunication();
|
||
|
||
void setAddress(unsigned short address);
|
||
|
||
virtual void process();
|
||
};
|
||
|
||
}
|
||
|
||
|
||
|
||
#endif /* SOURCES_DRIVERS_SLIPCOMMUNICATION_H_ */
|