Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ait_link.cpp@0:8e8dfc870cb2, 2016-04-04 (annotated)
- Committer:
- bhepp
- Date:
- Mon Apr 04 11:19:55 2016 +0000
- Revision:
- 0:8e8dfc870cb2
- Child:
- 3:bfc4928cd279
Initial
Who changed what in which revision?
| User | Revision | Line number | New 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 |