Benjamin Hepp / ait_link
Committer:
bhepp
Date:
Mon Apr 04 11:19:55 2016 +0000
Revision:
0:8e8dfc870cb2
Child:
3:bfc4928cd279
Initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bhepp 0:8e8dfc870cb2 1 // Adapted by Benjamin Hepp from ArduHDLC library
bhepp 0:8e8dfc870cb2 2
bhepp 0:8e8dfc870cb2 3 /*
bhepp 0:8e8dfc870cb2 4 Arduhdlc is Arduino HDLC library, which can be used over any interface.
bhepp 0:8e8dfc870cb2 5 Copyright (C) 2015 Jarkko Hautakorpi et al. see LICENSE.txt
bhepp 0:8e8dfc870cb2 6 This program is free software; you can redistribute it and/or
bhepp 0:8e8dfc870cb2 7 modify it under the terms of the GNU General Public License
bhepp 0:8e8dfc870cb2 8 as published by the Free Software Foundation; either version 2
bhepp 0:8e8dfc870cb2 9 of the License, or (at your option) any later version.
bhepp 0:8e8dfc870cb2 10 This program is distributed in the hope that it will be useful,
bhepp 0:8e8dfc870cb2 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
bhepp 0:8e8dfc870cb2 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
bhepp 0:8e8dfc870cb2 13 GNU General Public License for more details.
bhepp 0:8e8dfc870cb2 14 You should have received a copy of the GNU General Public License
bhepp 0:8e8dfc870cb2 15 along with this program; if not, write to the Free Software
bhepp 0:8e8dfc870cb2 16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
bhepp 0:8e8dfc870cb2 17 */
bhepp 0:8e8dfc870cb2 18
bhepp 0:8e8dfc870cb2 19
bhepp 0:8e8dfc870cb2 20 #include "ait_link/ait_link.h"
bhepp 0:8e8dfc870cb2 21
bhepp 0:8e8dfc870cb2 22 using namespace ait;
bhepp 0:8e8dfc870cb2 23
bhepp 0:8e8dfc870cb2 24 /* 16bit low and high bytes copier */
bhepp 0:8e8dfc870cb2 25 #define low(x) ((x) & 0xFF)
bhepp 0:8e8dfc870cb2 26 #define high(x) (((x)>>8) & 0xFF)
bhepp 0:8e8dfc870cb2 27
bhepp 0:8e8dfc870cb2 28 AITLink::AITLink(size_t max_frame_length)
bhepp 0:8e8dfc870cb2 29 {
bhepp 0:8e8dfc870cb2 30 frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 0:8e8dfc870cb2 31 escape_character = false;
bhepp 0:8e8dfc870cb2 32 frame_position = 0;
bhepp 0:8e8dfc870cb2 33 this->max_frame_length = max_frame_length;
bhepp 0:8e8dfc870cb2 34 receive_frame_buffer = new uint8_t[max_frame_length+1]; // char* ab = (char*)malloc(12);
bhepp 0:8e8dfc870cb2 35 handle_frame_callback = NULL;
bhepp 0:8e8dfc870cb2 36 callback_user_data = NULL;
bhepp 0:8e8dfc870cb2 37 }
bhepp 0:8e8dfc870cb2 38
bhepp 0:8e8dfc870cb2 39 AITLink::~AITLink()
bhepp 0:8e8dfc870cb2 40 {
bhepp 0:8e8dfc870cb2 41 delete[] receive_frame_buffer;
bhepp 0:8e8dfc870cb2 42 }
bhepp 0:8e8dfc870cb2 43
bhepp 0:8e8dfc870cb2 44 /* Wrap given data in HDLC frame and send it out byte at a time*/
bhepp 0:8e8dfc870cb2 45 bool AITLink::sendFrame(const uint8_t* frame_buffer, size_t frame_length)
bhepp 0:8e8dfc870cb2 46 {
bhepp 0:8e8dfc870cb2 47 if (frame_length > max_frame_length) {
bhepp 0:8e8dfc870cb2 48 return false;
bhepp 0:8e8dfc870cb2 49 }
bhepp 0:8e8dfc870cb2 50
bhepp 0:8e8dfc870cb2 51 uint8_t data;
bhepp 0:8e8dfc870cb2 52 uint16_t fcs = CRC16_CCITT_INIT_VAL;
bhepp 0:8e8dfc870cb2 53
bhepp 0:8e8dfc870cb2 54 sendChar(FRAME_BOUNDARY_OCTET);
bhepp 0:8e8dfc870cb2 55
bhepp 0:8e8dfc870cb2 56 while (frame_length)
bhepp 0:8e8dfc870cb2 57 {
bhepp 0:8e8dfc870cb2 58 data = *frame_buffer++;
bhepp 0:8e8dfc870cb2 59 fcs = crcCcittUpdate(fcs, data);
bhepp 0:8e8dfc870cb2 60 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 0:8e8dfc870cb2 61 {
bhepp 0:8e8dfc870cb2 62 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 0:8e8dfc870cb2 63 data ^= INVERT_OCTET;
bhepp 0:8e8dfc870cb2 64 }
bhepp 0:8e8dfc870cb2 65 sendChar(data);
bhepp 0:8e8dfc870cb2 66 --frame_length;
bhepp 0:8e8dfc870cb2 67 }
bhepp 0:8e8dfc870cb2 68 data = low(fcs);
bhepp 0:8e8dfc870cb2 69 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 0:8e8dfc870cb2 70 {
bhepp 0:8e8dfc870cb2 71 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 0:8e8dfc870cb2 72 data ^= INVERT_OCTET;
bhepp 0:8e8dfc870cb2 73 }
bhepp 0:8e8dfc870cb2 74 sendChar(data);
bhepp 0:8e8dfc870cb2 75 data = high(fcs);
bhepp 0:8e8dfc870cb2 76 if ((data == CONTROL_ESCAPE_OCTET) || (data == FRAME_BOUNDARY_OCTET))
bhepp 0:8e8dfc870cb2 77 {
bhepp 0:8e8dfc870cb2 78 sendChar(CONTROL_ESCAPE_OCTET);
bhepp 0:8e8dfc870cb2 79 data ^= INVERT_OCTET;
bhepp 0:8e8dfc870cb2 80 }
bhepp 0:8e8dfc870cb2 81 sendChar(data);
bhepp 0:8e8dfc870cb2 82 sendChar(FRAME_BOUNDARY_OCTET);
bhepp 0:8e8dfc870cb2 83
bhepp 0:8e8dfc870cb2 84 return true;
bhepp 0:8e8dfc870cb2 85 }
bhepp 0:8e8dfc870cb2 86
bhepp 0:8e8dfc870cb2 87 /* Function to find valid HDLC frame from incoming data */
bhepp 0:8e8dfc870cb2 88 void AITLink::inputReceivedChar(uint8_t data)
bhepp 0:8e8dfc870cb2 89 {
bhepp 0:8e8dfc870cb2 90 /* FRAME FLAG */
bhepp 0:8e8dfc870cb2 91 if (data == FRAME_BOUNDARY_OCTET)
bhepp 0:8e8dfc870cb2 92 {
bhepp 0:8e8dfc870cb2 93 if (this->escape_character == true)
bhepp 0:8e8dfc870cb2 94 {
bhepp 0:8e8dfc870cb2 95 this->escape_character = false;
bhepp 0:8e8dfc870cb2 96 }
bhepp 0:8e8dfc870cb2 97 /* If a valid frame is detected */
bhepp 0:8e8dfc870cb2 98 else if ( (this->frame_position >= 2) &&
bhepp 0:8e8dfc870cb2 99 ( 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 0:8e8dfc870cb2 100 {
bhepp 0:8e8dfc870cb2 101 /* Call the user defined function and pass frame to it */
bhepp 0:8e8dfc870cb2 102 handleFrame(receive_frame_buffer, this->frame_position - 2);
bhepp 0:8e8dfc870cb2 103 }
bhepp 0:8e8dfc870cb2 104 this->frame_position = 0;
bhepp 0:8e8dfc870cb2 105 this->frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 0:8e8dfc870cb2 106 return;
bhepp 0:8e8dfc870cb2 107 }
bhepp 0:8e8dfc870cb2 108
bhepp 0:8e8dfc870cb2 109 if (this->escape_character)
bhepp 0:8e8dfc870cb2 110 {
bhepp 0:8e8dfc870cb2 111 this->escape_character = false;
bhepp 0:8e8dfc870cb2 112 data ^= INVERT_OCTET;
bhepp 0:8e8dfc870cb2 113 }
bhepp 0:8e8dfc870cb2 114 else if (data == CONTROL_ESCAPE_OCTET)
bhepp 0:8e8dfc870cb2 115 {
bhepp 0:8e8dfc870cb2 116 this->escape_character = true;
bhepp 0:8e8dfc870cb2 117 return;
bhepp 0:8e8dfc870cb2 118 }
bhepp 0:8e8dfc870cb2 119
bhepp 0:8e8dfc870cb2 120 receive_frame_buffer[this->frame_position] = data;
bhepp 0:8e8dfc870cb2 121
bhepp 0:8e8dfc870cb2 122 if (this->frame_position >= 2) {
bhepp 0:8e8dfc870cb2 123 this->frame_checksum = crcCcittUpdate(this->frame_checksum, receive_frame_buffer[this->frame_position - 2]);
bhepp 0:8e8dfc870cb2 124 }
bhepp 0:8e8dfc870cb2 125
bhepp 0:8e8dfc870cb2 126 this->frame_position++;
bhepp 0:8e8dfc870cb2 127
bhepp 0:8e8dfc870cb2 128 if (this->frame_position >= this->max_frame_length)
bhepp 0:8e8dfc870cb2 129 {
bhepp 0:8e8dfc870cb2 130 this->frame_position = 0;
bhepp 0:8e8dfc870cb2 131 this->frame_checksum = CRC16_CCITT_INIT_VAL;
bhepp 0:8e8dfc870cb2 132 }
bhepp 0:8e8dfc870cb2 133 }
bhepp 0:8e8dfc870cb2 134
bhepp 0:8e8dfc870cb2 135 void AITLink::registerFrameHandler(void (*callback)(void* user_data, const uint8_t* frame_buffer, size_t frame_length), void* user_data)
bhepp 0:8e8dfc870cb2 136 {
bhepp 0:8e8dfc870cb2 137 handle_frame_callback = callback;
bhepp 0:8e8dfc870cb2 138 callback_user_data = user_data;
bhepp 0:8e8dfc870cb2 139 }
bhepp 0:8e8dfc870cb2 140
bhepp 0:8e8dfc870cb2 141 void AITLink::handleFrame(const uint8_t* frame_buffer, size_t frame_length)
bhepp 0:8e8dfc870cb2 142 {
bhepp 0:8e8dfc870cb2 143 if (handle_frame_callback != NULL) {
bhepp 0:8e8dfc870cb2 144 (*handle_frame_callback)(callback_user_data, frame_buffer, frame_length);
bhepp 0:8e8dfc870cb2 145 }
bhepp 0:8e8dfc870cb2 146
bhepp 0:8e8dfc870cb2 147 }
bhepp 0:8e8dfc870cb2 148
bhepp 0:8e8dfc870cb2 149 uint16_t AITLink::crcCcittUpdate(uint16_t crc, uint8_t data)
bhepp 0:8e8dfc870cb2 150 {
bhepp 0:8e8dfc870cb2 151 data ^= low(crc);
bhepp 0:8e8dfc870cb2 152 data ^= data << 4;
bhepp 0:8e8dfc870cb2 153
bhepp 0:8e8dfc870cb2 154 return (
bhepp 0:8e8dfc870cb2 155 ( ((uint16_t)data << 8) | high(crc) ) ^ ((uint8_t)data >> 4) ^ ((uint16_t)data << 3)
bhepp 0:8e8dfc870cb2 156 );
bhepp 0:8e8dfc870cb2 157 }
bhepp 0:8e8dfc870cb2 158