MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/driver/SlipCommunication.cpp

437 lines
9.2 KiB
C++

/*
* 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;
}