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@3:bfc4928cd279, 2016-04-06 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |