MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/driver/SlipCommunication.cpp
2024-06-07 11:12:56 +03:00

437 lines
9.6 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.

/*
* SlipCommunication.cpp
*
* Created on: 31 марта 2017 г.
* Author: titov
*/
#include "SlipCommunication.hh"
//#include "../common/Literals.hh"
namespace driver {
//!< Объединение для конвертации двухбайтовых велечин в побайтовые
union TUShortToBytes
{
unsigned short UShortValue; //!<Двубайтовая целочисленная переменная
//!<Массив из двух байт.
struct
{
unsigned short Lo:8; //!<Младшая часть двубайтовой переменной
unsigned short Hi:8; //!<Старшая часть двубайтовой переменной
} byteValue; //!<массив из двух байт
};
void SlipCommunication::recieve_restart() {
count_head_byte = count_data_byte = count_crc16_byte = 0;
receive_mode = TReceiveMode::HEAD;
data_ready = false;
}
void SlipCommunication::create_packet() {
if(crc16rec.get() == packet_crc16 ) {
//В этот момент пакет полностью принят.
totalRecLength = packet_head.packet_size;
incoming_packet++;
//Прием пакета закончен, ожидаем новый пакет.
recieve_restart();
} else {
//Сбрасываем неправильные данные.
recieveReset();
}
}
bool SlipCommunication::packet_end() const {
return !(count_head_byte || count_data_byte || count_crc16_byte) || (receive_mode == TReceiveMode::STOP);
}
bool SlipCommunication::data_collection(char byte) {
switch(receive_mode) {
case TReceiveMode::HEAD: {
crc16rec.calcPartial(&byte, 1, !count_head_byte);
head_buff[count_head_byte] = byte;
count_head_byte++;
if(count_head_byte == head_size) {
packet_head.deserialize(head_buff);
bool addressed = (packet_head.hw_address == hw_address || packet_head.hw_address == 0xFFFFU);
if(!addressed)
receive_mode = TReceiveMode::SLEEP;
else if(packet_head.packet_size > 0 && packet_head.packet_size < max_datasize)
receive_mode = TReceiveMode::DATA;
else if(packet_head.packet_size == 0)
receive_mode = TReceiveMode::CRC16;
else
recieve_restart();
}
break;
}
case TReceiveMode::DATA: {
crc16rec.calcPartial(&byte, 1 , false);
receiveBuffer.put(byte);
count_data_byte++;
if(count_data_byte == packet_head.packet_size) {
receive_mode = TReceiveMode::CRC16;
}
break;
}
case TReceiveMode::CRC16: {
crc16_buff[count_crc16_byte] = byte;
count_crc16_byte++;
if(count_crc16_byte == crc16_size) {
deserialize_crc16();
receive_mode = TReceiveMode::STOP;
}
break;
}
default: break;
}
return receive_mode == TReceiveMode::STOP;
}
unsigned short SlipCommunication::slip_decode(char byte) {
if(byte_db_recived) {
byte_db_recived = false;
switch(byte) {
case TSlipDecode::DC:
return 0xC0u;//(TSlipDecode::C0 & 0xFFu);
case TSlipDecode::DD:
return 0xDBu;//(TSlipDecode::DB & 0xFFu);
default:
return TSlipDecode::ERROR;
}
} else {
switch(byte) {
case TSlipDecode::DB:
byte_db_recived = true;
return TSlipDecode::NOTBYTE;
case TSlipDecode::C0:
return TSlipDecode::END;
default:
return byte;
}
}
}
bool SlipCommunication::byte_processing(char byte) {
unsigned short symbol = slip_decode(byte); //Декодируем байт.
switch(symbol) { //Обрабатываем байт ->
case TSlipDecode::ERROR:
recieveReset(); //Сбрасываем данные.
break;
case TSlipDecode::NOTBYTE:
break; //Пропускаем байт.
case TSlipDecode::END:
if(data_ready) create_packet(); //Оформляем пакет.
else recieveReset(); //Сбрасываем данные.
break;
default:
if(data_ready) recieveReset(); //Сбрасываем данные.
else data_ready = data_collection(symbol); //Собираем данные.
break;
}
return packet_end(); //Возращаем признак окончания пакета.
}
bool SlipCommunication::slip_send(char byte) {
bool result;
char tmpByte[2];
switch( byte ) {
case TSlipDecode::C0:
tmpByte[0] = 0xDBu;//TSlipDecode::DB;
tmpByte[1] = 0xDCu;//TSlipDecode::DC;
result = bus.send( tmpByte, 2 );
break;
case TSlipDecode::DB:
tmpByte[0] = 0xDBu;//TSlipDecode::DB;
tmpByte[1] = 0xDDu;//TSlipDecode::DD;
result = bus.send( tmpByte, 2 );
break;
default:
result = bus.send( &byte, 1 );
break;
}
return result;
}
bool SlipCommunication::send_word_without_crc(unsigned short word) {
bool result;
TUShortToBytes convert;
char tmpc;
convert.UShortValue = word;
tmpc = convert.byteValue.Lo;
result = slip_send(tmpc);
tmpc = convert.byteValue.Hi;
result = result && slip_send(tmpc);
return result;
}
bool SlipCommunication::send_word_with_crc(unsigned short word) {
bool result;
TUShortToBytes convert;
char tmpc;
convert.UShortValue = word;
tmpc = convert.byteValue.Lo;
crc16send.calcPartial( &tmpc, 1, false );
result = slip_send(tmpc);
tmpc = convert.byteValue.Hi;
crc16send.calcPartial( &tmpc, 1, false );
result = result && slip_send( tmpc );
return result;
}
void SlipCommunication::deserialize_crc16() {
TUShortToBytes converter;
converter.byteValue.Lo = crc16_buff[0];
converter.byteValue.Hi = crc16_buff[1];
packet_crc16 = converter.UShortValue;
}
void SlipCommunication::recieveReset() {
// while(count_data_byte--) {
// char temp;
// receiveBuffer->Pop(&temp);
// }
receiveBuffer.clear();
incoming_packet = 0;
recieve_restart();
}
bool SlipCommunication::sendHead(unsigned short id, unsigned short size) noexcept {
bool result;
packet_start = true;
de.on();
crc16send.calcPartial( 0, 0, true );
result = send_word_with_crc(size);
result = result && send_word_with_crc(id);
result = result && send_byte_with_crc(hw_address);
return result;
}
bool SlipCommunication::sendEnd() noexcept {
char tmpc = TSlipDecode::C0;
packet_start = false;
return send_word_without_crc(crc16send.get()) && bus.send( &tmpc, 1 );
}
void SlipCommunication::send_reset() {
char tmpc = TSlipDecode::C0;
bus.reset();
bus.send( &tmpc, 1 );
}
SlipCommunication::SlipCommunication(
peripheral::IUartPort & bus,
driver::IDiscreteOutput & de ) :
bus(bus), de(de),
receiveBuffer(),
error_count(0),
max_error(1000u),
bus_enable(true),
hw_address(0),
packet_crc16(0),
max_datasize(128),
incoming_packet(0),
totalRecLength(0),
byte_db_recived(false),
count_crc16_byte(0),
count_data_byte(0),
count_head_byte(0),
data_ready(false),
packet_head(),
receive_mode(TReceiveMode::HEAD),
timeout() {
recieve_restart();
}
SlipCommunication::~SlipCommunication() {}
unsigned short SlipCommunication::recieve_word() {
char tmpc;
TUShortToBytes converter;
tmpc = receiveBuffer.push();
converter.byteValue.Lo = tmpc;
tmpc = receiveBuffer.push();
converter.byteValue.Hi = tmpc;
return converter.UShortValue;
}
void SlipCommunication::setAddress(unsigned short address) {
hw_address = address;
}
bool SlipCommunication::send_byte_with_crc(unsigned char byte) {
bool result;
char tmpc = byte;
crc16send.calcPartial( &tmpc, 1, false );
result = slip_send(tmpc);
return result;
}
void SlipCommunication::process() {
bool error = bus.isRecieptionError();
if( bus_enable && error )
++error_count;
if( error )
bus.reset();
// if(bus_enable && error_count > max_error) {
// bus.receivedReset();
// bus.intDisable();
// bus_enable = false;
// }
int i = 32;
char byte;
while(!incoming_packet && i-- && bus.receive(&byte, 1)) {
error_count = 0;
byte_processing(byte);
}
if( ( bus.isDataSent() and not packet_start ) )
de.off();
}
void SlipCommunication::THead::deserialize(char (&buff)[head_size]) {
TUShortToBytes converter;
converter.byteValue.Lo = buff[0];
converter.byteValue.Hi = buff[1];
packet_size = converter.UShortValue;
converter.byteValue.Lo = buff[2];
converter.byteValue.Hi = buff[3];
packet_id = converter.UShortValue;
hw_address = buff[4];
}
bool SlipCommunication::recieve_data(char * data, short length) {
bool result = incoming_packet;
if( incoming_packet ) {
char * ptr_data = reinterpret_cast<char *>(data);
int i;
for(i = 0; i < length && totalRecLength; i++, totalRecLength-- )
ptr_data[i] = recieve_byte();
if( totalRecLength == 0 && i != length ) result = false;
if( totalRecLength == 0 ) incoming_packet--;
}
return result;
}
bool SlipCommunication::send_packet(unsigned short id, const char * data, short length) {
return sendHead(id, length) && send(data, length) && sendEnd();
}
char SlipCommunication::recieve_byte() {
return receiveBuffer.push();
}
bool driver::SlipCommunication::send( const char * data, std::size_t size ) {
bool result = true;
const unsigned short * ptr_data = reinterpret_cast<const unsigned short *>(data);
for( int i = 0; i < size; i++ )
result = result && send_word_with_crc(ptr_data[i]);
return result;
}
bool driver::SlipCommunication::receive( char * data, std::size_t size ) {
bool result = incoming_packet;
if( incoming_packet )
{
unsigned short * ptr_data = reinterpret_cast<unsigned short *>(data);
int i;
for(i = 0; i < size && totalRecLength; i++, totalRecLength -= 2 )
ptr_data[i] = recieve_word();
if( totalRecLength == 0 && i != size ) result = false;
if( totalRecLength == 0 ) incoming_packet--;
}
return result;
}
}
std::pair<bool, unsigned short> driver::SlipCommunication::isPacketAvailable() const {
return std::pair<bool, unsigned short>( incoming_packet, packet_head.packet_id );
}
bool driver::SlipCommunication::isPacketSent() const {
return bus.isDataSent() and not packet_start;
}