Benjamin Hepp / ait_link
Committer:
bhepp
Date:
Wed Apr 06 08:27:25 2016 +0000
Revision:
3:bfc4928cd279
Parent:
0:8e8dfc870cb2
Updated license

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bhepp 3:bfc4928cd279 1 //
bhepp 3:bfc4928cd279 2 // HDLC based serial communication class.
bhepp 3:bfc4928cd279 3 //
bhepp 3:bfc4928cd279 4 // Adapted by Benjamin Hepp from ArduHDLC library (see LICENSE.txt)
bhepp 3:bfc4928cd279 5 // Original work Copyright (c) 2015 Jarkko Hautakorpi et al.
bhepp 3:bfc4928cd279 6 // Modified work Copyright (c) 2016 Benjamin Hepp.
bhepp 3:bfc4928cd279 7
bhepp 3:bfc4928cd279 8 #include "ait_link/ait_link.h"
bhepp 3:bfc4928cd279 9
bhepp 3:bfc4928cd279 10 using namespace ait;
bhepp 3:bfc4928cd279 11
bhepp 3:bfc4928cd279 12 /* 16bit low and high bytes copier */
bhepp 3:bfc4928cd279 13 #define low(x) ((x) & 0xFF)
bhepp 3:bfc4928cd279 14 #define high(x) (((x)>>8) & 0xFF)
bhepp 3:bfc4928cd279 15
bhepp 3:bfc4928cd279 16 AITLink::AITLink(size_t max_frame_length)
bhepp 3:bfc4928cd279 17 {
bhepp 3:bfc4928cd279 18 frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 3:bfc4928cd279 19 escape_character = false;
bhepp 3:bfc4928cd279 20 frame_position = 0;
bhepp 3:bfc4928cd279 21 this->max_frame_length = max_frame_length;
bhepp 3:bfc4928cd279 22 receive_frame_buffer = new uint8_t[max_frame_length+1]; // char* ab = (char*)malloc(12);
bhepp 3:bfc4928cd279 23 handle_frame_callback = NULL;
bhepp 3:bfc4928cd279 24 callback_user_data = NULL;
bhepp 3:bfc4928cd279 25 }
bhepp 3:bfc4928cd279 26
bhepp 3:bfc4928cd279 27 AITLink::~AITLink()
bhepp 3:bfc4928cd279 28 {
bhepp 3:bfc4928cd279 29 delete[] receive_frame_buffer;
bhepp 3:bfc4928cd279 30 }
bhepp 3:bfc4928cd279 31
bhepp 3:bfc4928cd279 32 /* Wrap given data in HDLC frame and send it out byte at a time*/
bhepp 3:bfc4928cd279 33 bool AITLink::sendFrame(const uint8_t* frame_buffer, size_t frame_length)
bhepp 3:bfc4928cd279 34 {
bhepp 3:bfc4928cd279 35 if (frame_length > max_frame_length) {
bhepp 3:bfc4928cd279 36 return false;
bhepp 3:bfc4928cd279 37 }
bhepp 3:bfc4928cd279 38
bhepp 3:bfc4928cd279 39 uint8_t data;
bhepp 3:bfc4928cd279 40 uint16_t fcs = CRC16_CCITT_INIT_VAL;
bhepp 3:bfc4928cd279 41
bhepp 3:bfc4928cd279 42 sendChar(FRAME_BOUNDARY_OCTET);
bhepp 3:bfc4928cd279 43
bhepp 3:bfc4928cd279 44 while (frame_length)
bhepp 3:bfc4928cd279 45 {
bhepp 3:bfc4928cd279 46 data = *frame_buffer++;
bhepp 3:bfc4928cd279 47 fcs = crcCcittUpdate(fcs, data);
bhepp 3:bfc4928cd279 48 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 3:bfc4928cd279 49 {
bhepp 3:bfc4928cd279 50 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 3:bfc4928cd279 51 data ^= INVERT_OCTET;
bhepp 3:bfc4928cd279 52 }
bhepp 3:bfc4928cd279 53 sendChar(data);
bhepp 3:bfc4928cd279 54 --frame_length;
bhepp 3:bfc4928cd279 55 }
bhepp 3:bfc4928cd279 56 data = low(fcs);
bhepp 3:bfc4928cd279 57 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 3:bfc4928cd279 58 {
bhepp 3:bfc4928cd279 59 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 3:bfc4928cd279 60 data ^= INVERT_OCTET;
bhepp 3:bfc4928cd279 61 }
bhepp 3:bfc4928cd279 62 sendChar(data);
bhepp 3:bfc4928cd279 63 data = high(fcs);
bhepp 3:bfc4928cd279 64 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 3:bfc4928cd279 65 {
bhepp 3:bfc4928cd279 66 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 3:bfc4928cd279 67 data ^= INVERT_OCTET;
bhepp 3:bfc4928cd279 68 }
bhepp 3:bfc4928cd279 69 sendChar(data);
bhepp 3:bfc4928cd279 70 sendChar(FRAME_BOUNDARY_OCTET);
bhepp 0:8e8dfc870cb2 71
bhepp 3:bfc4928cd279 72 return true;
bhepp 3:bfc4928cd279 73 }
bhepp 3:bfc4928cd279 74
bhepp 3:bfc4928cd279 75 /* Function to find valid HDLC frame from incoming data */
bhepp 3:bfc4928cd279 76 void AITLink::inputReceivedChar(uint8_t data)
bhepp 3:bfc4928cd279 77 {
bhepp 3:bfc4928cd279 78 /* FRAME FLAG */
bhepp 3:bfc4928cd279 79 if (data == FRAME_BOUNDARY_OCTET)
bhepp 3:bfc4928cd279 80 {
bhepp 3:bfc4928cd279 81 if (this->escape_character == true)
bhepp 3:bfc4928cd279 82 {
bhepp 3:bfc4928cd279 83 this->escape_character = false;
bhepp 3:bfc4928cd279 84 }
bhepp 3:bfc4928cd279 85 /* If a valid frame is detected */
bhepp 3:bfc4928cd279 86 else if ( (this->frame_position >= 2) &&
bhepp 3:bfc4928cd279 87 ( this->frame_checksum == ((this->receive_frame_buffer[this->frame_position-1] << 8 ) | (this->receive_frame_buffer[this->frame_position-2] & 0xff)) ) ) // (msb << 8 ) | (lsb & 0xff)
bhepp 3:bfc4928cd279 88 {
bhepp 3:bfc4928cd279 89 /* Call the user defined function and pass frame to it */
bhepp 3:bfc4928cd279 90 handleFrame(receive_frame_buffer, this->frame_position - 2);
bhepp 3:bfc4928cd279 91 }
bhepp 3:bfc4928cd279 92 this->frame_position = 0;
bhepp 3:bfc4928cd279 93 this->frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 3:bfc4928cd279 94 return;
bhepp 3:bfc4928cd279 95 }
bhepp 3:bfc4928cd279 96
bhepp 3:bfc4928cd279 97 if (this->escape_character)
bhepp 3:bfc4928cd279 98 {
bhepp 3:bfc4928cd279 99 this->escape_character = false;
bhepp 3:bfc4928cd279 100 data ^= INVERT_OCTET;
bhepp 3:bfc4928cd279 101 }
bhepp 3:bfc4928cd279 102 else if (data == CONTROL_ESCAPE_OCTET)
bhepp 3:bfc4928cd279 103 {
bhepp 3:bfc4928cd279 104 this->escape_character = true;
bhepp 3:bfc4928cd279 105 return;
bhepp 3:bfc4928cd279 106 }
bhepp 3:bfc4928cd279 107
bhepp 3:bfc4928cd279 108 receive_frame_buffer[this->frame_position] = data;
bhepp 3:bfc4928cd279 109
bhepp 3:bfc4928cd279 110 if (this->frame_position >= 2) {
bhepp 3:bfc4928cd279 111 this->frame_checksum = crcCcittUpdate(this->frame_checksum, receive_frame_buffer[this->frame_position - 2]);
bhepp 3:bfc4928cd279 112 }
bhepp 3:bfc4928cd279 113
bhepp 3:bfc4928cd279 114 this->frame_position++;
bhepp 3:bfc4928cd279 115
bhepp 3:bfc4928cd279 116 if (this->frame_position >= this->max_frame_length)
bhepp 3:bfc4928cd279 117 {
bhepp 3:bfc4928cd279 118 this->frame_position = 0;
bhepp 3:bfc4928cd279 119 this->frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 3:bfc4928cd279 120 }
bhepp 3:bfc4928cd279 121 }
bhepp 3:bfc4928cd279 122
bhepp 3:bfc4928cd279 123 void AITLink::registerFrameHandler(void (*callback)(void* user_data, const uint8_t* frame_buffer, size_t frame_length), void* user_data)
bhepp 3:bfc4928cd279 124 {
bhepp 3:bfc4928cd279 125 handle_frame_callback = callback;
bhepp 3:bfc4928cd279 126 callback_user_data = user_data;
bhepp 3:bfc4928cd279 127 }
bhepp 3:bfc4928cd279 128
bhepp 3:bfc4928cd279 129 void AITLink::handleFrame(const uint8_t* frame_buffer, size_t frame_length)
bhepp 3:bfc4928cd279 130 {
bhepp 3:bfc4928cd279 131 if (handle_frame_callback != NULL) {
bhepp 3:bfc4928cd279 132 (*handle_frame_callback)(callback_user_data, frame_buffer, frame_length);
bhepp 3:bfc4928cd279 133 }
bhepp 3:bfc4928cd279 134
bhepp 3:bfc4928cd279 135 }
bhepp 3:bfc4928cd279 136
bhepp 3:bfc4928cd279 137 uint16_t AITLink::crcCcittUpdate(uint16_t crc, uint8_t data)
bhepp 3:bfc4928cd279 138 {
bhepp 3:bfc4928cd279 139 data ^= low(crc);
bhepp 3:bfc4928cd279 140 data ^= data << 4;
bhepp 3:bfc4928cd279 141
bhepp 3:bfc4928cd279 142 return (
bhepp 3:bfc4928cd279 143 ( ((uint16_t)data << 8) | high(crc) ) ^ ((uint8_t)data >> 4) ^ ((uint16_t)data << 3)
bhepp 3:bfc4928cd279 144 );
bhepp 3:bfc4928cd279 145 }