/* * 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 #include 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 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 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_ */