Framework for reading and writing variables in real time on any MBED platform.
DistantIO
This is the C implementation of the DistantIO slave framework.
Library is working but slight API breaks may occur in the future. C++ version is also in development.
To get the master-side implementation, see https://github.com/Overdrivr/DistantIO
protocol.cpp@0:c4676d32d381, 2015-09-15 (annotated)
- Committer:
- Overdrivr
- Date:
- Tue Sep 15 15:27:55 2015 +0000
- Revision:
- 0:c4676d32d381
- Child:
- 1:aaffeb93f99b
Version not bug free (especially names should not be longer thant 8 characters or have spaces), but pretty reliable behavior. See github repo for tickets
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Overdrivr | 0:c4676d32d381 | 1 | /* |
Overdrivr | 0:c4676d32d381 | 2 | * serial_protocol.c |
Overdrivr | 0:c4676d32d381 | 3 | * |
Overdrivr | 0:c4676d32d381 | 4 | * Created on: Oct 22, 2014 |
Overdrivr | 0:c4676d32d381 | 5 | * Author: B48923 |
Overdrivr | 0:c4676d32d381 | 6 | */ |
Overdrivr | 0:c4676d32d381 | 7 | |
Overdrivr | 0:c4676d32d381 | 8 | #include "protocol.h" |
Overdrivr | 0:c4676d32d381 | 9 | |
Overdrivr | 0:c4676d32d381 | 10 | enum state |
Overdrivr | 0:c4676d32d381 | 11 | { |
Overdrivr | 0:c4676d32d381 | 12 | IDLE, |
Overdrivr | 0:c4676d32d381 | 13 | IN_PROCESS |
Overdrivr | 0:c4676d32d381 | 14 | }; |
Overdrivr | 0:c4676d32d381 | 15 | typedef enum state state; |
Overdrivr | 0:c4676d32d381 | 16 | |
Overdrivr | 0:c4676d32d381 | 17 | |
Overdrivr | 0:c4676d32d381 | 18 | enum ESC_state |
Overdrivr | 0:c4676d32d381 | 19 | { |
Overdrivr | 0:c4676d32d381 | 20 | NONE, |
Overdrivr | 0:c4676d32d381 | 21 | NEXT |
Overdrivr | 0:c4676d32d381 | 22 | }; |
Overdrivr | 0:c4676d32d381 | 23 | typedef enum ESC_state ESC_state; |
Overdrivr | 0:c4676d32d381 | 24 | |
Overdrivr | 0:c4676d32d381 | 25 | uint16_t decodingIndex; |
Overdrivr | 0:c4676d32d381 | 26 | state protocol_state; |
Overdrivr | 0:c4676d32d381 | 27 | ESC_state escape_state; |
Overdrivr | 0:c4676d32d381 | 28 | |
Overdrivr | 0:c4676d32d381 | 29 | uint8_t SOF_; |
Overdrivr | 0:c4676d32d381 | 30 | uint8_t EOF_; |
Overdrivr | 0:c4676d32d381 | 31 | uint8_t ESC_; |
Overdrivr | 0:c4676d32d381 | 32 | |
Overdrivr | 0:c4676d32d381 | 33 | static void (*on_encoding_done)(uint8_t* data, uint16_t size); |
Overdrivr | 0:c4676d32d381 | 34 | static void (*on_decoding_done)(uint8_t* data, uint16_t size); |
Overdrivr | 0:c4676d32d381 | 35 | |
Overdrivr | 0:c4676d32d381 | 36 | |
Overdrivr | 0:c4676d32d381 | 37 | void init_protocol(void (*encoding_done_callback)(uint8_t*,uint16_t),void (*decoding_done_callback)(uint8_t*,uint16_t)) |
Overdrivr | 0:c4676d32d381 | 38 | { |
Overdrivr | 0:c4676d32d381 | 39 | protocol_state = IDLE; |
Overdrivr | 0:c4676d32d381 | 40 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 41 | |
Overdrivr | 0:c4676d32d381 | 42 | SOF_ = 0xF7; |
Overdrivr | 0:c4676d32d381 | 43 | EOF_ = 0x7F; |
Overdrivr | 0:c4676d32d381 | 44 | ESC_ = 0x7D; |
Overdrivr | 0:c4676d32d381 | 45 | |
Overdrivr | 0:c4676d32d381 | 46 | decodingIndex = 0; |
Overdrivr | 0:c4676d32d381 | 47 | |
Overdrivr | 0:c4676d32d381 | 48 | on_encoding_done = encoding_done_callback; |
Overdrivr | 0:c4676d32d381 | 49 | on_decoding_done = decoding_done_callback; |
Overdrivr | 0:c4676d32d381 | 50 | } |
Overdrivr | 0:c4676d32d381 | 51 | |
Overdrivr | 0:c4676d32d381 | 52 | void encode(uint8_t* framedata, uint16_t framesize) |
Overdrivr | 0:c4676d32d381 | 53 | { |
Overdrivr | 0:c4676d32d381 | 54 | // If frame size is superior than maximum allowed, abort |
Overdrivr | 0:c4676d32d381 | 55 | if(framesize > ENCODING_BUFFER_SIZE) |
Overdrivr | 0:c4676d32d381 | 56 | return; |
Overdrivr | 0:c4676d32d381 | 57 | |
Overdrivr | 0:c4676d32d381 | 58 | // Actual buffer size is twice the data size (for worst case byte stuffing) + SOF + EOF |
Overdrivr | 0:c4676d32d381 | 59 | static uint8_t encodingBuffer[ENCODING_BUFFER_SIZE * 2 + 2]; |
Overdrivr | 0:c4676d32d381 | 60 | |
Overdrivr | 0:c4676d32d381 | 61 | uint16_t index = 0, i = 0; |
Overdrivr | 0:c4676d32d381 | 62 | |
Overdrivr | 0:c4676d32d381 | 63 | //Write start of frame / end of frame byte |
Overdrivr | 0:c4676d32d381 | 64 | encodingBuffer[index++] = SOF_; |
Overdrivr | 0:c4676d32d381 | 65 | |
Overdrivr | 0:c4676d32d381 | 66 | //Write data |
Overdrivr | 0:c4676d32d381 | 67 | for(i = 0 ; i < framesize ; i++) |
Overdrivr | 0:c4676d32d381 | 68 | { |
Overdrivr | 0:c4676d32d381 | 69 | //See serial_protocols_definition.xlsx |
Overdrivr | 0:c4676d32d381 | 70 | if(*(framedata + i) == SOF_ || |
Overdrivr | 0:c4676d32d381 | 71 | *(framedata + i) == EOF_ || |
Overdrivr | 0:c4676d32d381 | 72 | *(framedata + i) == ESC_) |
Overdrivr | 0:c4676d32d381 | 73 | { |
Overdrivr | 0:c4676d32d381 | 74 | //If data contains one of the flags, we escape it before |
Overdrivr | 0:c4676d32d381 | 75 | encodingBuffer[index++] = ESC_; |
Overdrivr | 0:c4676d32d381 | 76 | } |
Overdrivr | 0:c4676d32d381 | 77 | encodingBuffer[index++] = framedata[i]; |
Overdrivr | 0:c4676d32d381 | 78 | } |
Overdrivr | 0:c4676d32d381 | 79 | |
Overdrivr | 0:c4676d32d381 | 80 | encodingBuffer[index++] = EOF_; |
Overdrivr | 0:c4676d32d381 | 81 | |
Overdrivr | 0:c4676d32d381 | 82 | // Operation is done, call function callback |
Overdrivr | 0:c4676d32d381 | 83 | on_encoding_done(encodingBuffer,index); |
Overdrivr | 0:c4676d32d381 | 84 | } |
Overdrivr | 0:c4676d32d381 | 85 | |
Overdrivr | 0:c4676d32d381 | 86 | void decode(uint8_t received_byte) |
Overdrivr | 0:c4676d32d381 | 87 | { |
Overdrivr | 0:c4676d32d381 | 88 | static uint8_t decodingBuffer[DECODING_BUFFER_SIZE]; |
Overdrivr | 0:c4676d32d381 | 89 | |
Overdrivr | 0:c4676d32d381 | 90 | // If a reception was in process |
Overdrivr | 0:c4676d32d381 | 91 | if(protocol_state == IN_PROCESS) |
Overdrivr | 0:c4676d32d381 | 92 | { |
Overdrivr | 0:c4676d32d381 | 93 | // If the character was previously marked as pure data |
Overdrivr | 0:c4676d32d381 | 94 | if(escape_state == NEXT) |
Overdrivr | 0:c4676d32d381 | 95 | { |
Overdrivr | 0:c4676d32d381 | 96 | // If max buffer size was reached, cancel reception to avoid overflowing buffer |
Overdrivr | 0:c4676d32d381 | 97 | if(decodingIndex + 1 >= DECODING_BUFFER_SIZE) |
Overdrivr | 0:c4676d32d381 | 98 | { |
Overdrivr | 0:c4676d32d381 | 99 | decodingIndex = 0; |
Overdrivr | 0:c4676d32d381 | 100 | protocol_state = IDLE; |
Overdrivr | 0:c4676d32d381 | 101 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 102 | } |
Overdrivr | 0:c4676d32d381 | 103 | else |
Overdrivr | 0:c4676d32d381 | 104 | { |
Overdrivr | 0:c4676d32d381 | 105 | decodingBuffer[decodingIndex++] = received_byte; |
Overdrivr | 0:c4676d32d381 | 106 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 107 | } |
Overdrivr | 0:c4676d32d381 | 108 | } |
Overdrivr | 0:c4676d32d381 | 109 | else |
Overdrivr | 0:c4676d32d381 | 110 | { |
Overdrivr | 0:c4676d32d381 | 111 | // End of frame |
Overdrivr | 0:c4676d32d381 | 112 | if(received_byte == EOF_) |
Overdrivr | 0:c4676d32d381 | 113 | { |
Overdrivr | 0:c4676d32d381 | 114 | protocol_state = IDLE; |
Overdrivr | 0:c4676d32d381 | 115 | // Call the function callback for end of frame |
Overdrivr | 0:c4676d32d381 | 116 | on_decoding_done(decodingBuffer,decodingIndex); |
Overdrivr | 0:c4676d32d381 | 117 | } |
Overdrivr | 0:c4676d32d381 | 118 | else if(received_byte == ESC_) |
Overdrivr | 0:c4676d32d381 | 119 | { |
Overdrivr | 0:c4676d32d381 | 120 | escape_state = NEXT; |
Overdrivr | 0:c4676d32d381 | 121 | } |
Overdrivr | 0:c4676d32d381 | 122 | else |
Overdrivr | 0:c4676d32d381 | 123 | { |
Overdrivr | 0:c4676d32d381 | 124 | // If max buffer size was reached, cancel reception to avoid overflowing buffer |
Overdrivr | 0:c4676d32d381 | 125 | if(decodingIndex + 1 >= DECODING_BUFFER_SIZE) |
Overdrivr | 0:c4676d32d381 | 126 | { |
Overdrivr | 0:c4676d32d381 | 127 | decodingIndex = 0; |
Overdrivr | 0:c4676d32d381 | 128 | protocol_state = IDLE; |
Overdrivr | 0:c4676d32d381 | 129 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 130 | } |
Overdrivr | 0:c4676d32d381 | 131 | else |
Overdrivr | 0:c4676d32d381 | 132 | { |
Overdrivr | 0:c4676d32d381 | 133 | decodingBuffer[decodingIndex++] = received_byte; |
Overdrivr | 0:c4676d32d381 | 134 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 135 | } |
Overdrivr | 0:c4676d32d381 | 136 | } |
Overdrivr | 0:c4676d32d381 | 137 | } |
Overdrivr | 0:c4676d32d381 | 138 | } |
Overdrivr | 0:c4676d32d381 | 139 | else |
Overdrivr | 0:c4676d32d381 | 140 | { |
Overdrivr | 0:c4676d32d381 | 141 | if(received_byte == SOF_) |
Overdrivr | 0:c4676d32d381 | 142 | { |
Overdrivr | 0:c4676d32d381 | 143 | protocol_state = IN_PROCESS; |
Overdrivr | 0:c4676d32d381 | 144 | decodingIndex = 0; |
Overdrivr | 0:c4676d32d381 | 145 | escape_state = NONE; |
Overdrivr | 0:c4676d32d381 | 146 | } |
Overdrivr | 0:c4676d32d381 | 147 | else |
Overdrivr | 0:c4676d32d381 | 148 | { |
Overdrivr | 0:c4676d32d381 | 149 | //Received character outside a valid frame, ignore it |
Overdrivr | 0:c4676d32d381 | 150 | } |
Overdrivr | 0:c4676d32d381 | 151 | } |
Overdrivr | 0:c4676d32d381 | 152 | } |
Overdrivr | 0:c4676d32d381 | 153 | |
Overdrivr | 0:c4676d32d381 | 154 | |
Overdrivr | 0:c4676d32d381 | 155 |