Library for Manchester encoding using UART's hardware.

Dependents:   ManchesterUART_Transmitter ManchesterUART_Receiver

Manchester encoding using UART's hardware

This library implements Manchester code using UART. Each data byte is encoded into two bytes representing two nibbles of the original data. UART's hardware is then used to generate the Manchester encoded bit stream. Prior to decoding, the receiver converts the received bit stream to bytes using its UART. Start and stop patterns are sent to identify the boundaries (begin and end) of a data frame.

ACKNOWLEDGEMENT: The library is based on an article published by Adrian Mills.


Import programManchesterUART_Transmitter

Transmitter demo for the Manchester encoding library using UART's hardware.


Import programManchesterUART_Receiver

Receiver demo for the Manchester encoding library using UART's hardware.

NOTE: To perform a simple test (without radio link) connect the txPin on transmitter board to the rxPin on the receiver board and make sure that grounds are also connected one another.

Committer:
hudakz
Date:
Wed Nov 22 16:37:13 2017 +0000
Revision:
0:e076052bcffd
Child:
1:b869674fe56e
Initial release.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e076052bcffd 1 /*
hudakz 0:e076052bcffd 2 ******************************************************************************
hudakz 0:e076052bcffd 3 * @file ManchesterUART.cpp
hudakz 0:e076052bcffd 4 * @author Zoltan Hudak
hudakz 0:e076052bcffd 5 * @version
hudakz 0:e076052bcffd 6 * @date 2017-Nov-22
hudakz 0:e076052bcffd 7 * @brief Manchester code over UART for mbed
hudakz 0:e076052bcffd 8 ******************************************************************************
hudakz 0:e076052bcffd 9 * @attention
hudakz 0:e076052bcffd 10 *
hudakz 0:e076052bcffd 11 * <h2><center>&copy; COPYRIGHT(c) 2017 Zoltan Hudak <hudakz@outlook.com>
hudakz 0:e076052bcffd 12 *
hudakz 0:e076052bcffd 13 * All rights reserved.
hudakz 0:e076052bcffd 14
hudakz 0:e076052bcffd 15 This program is free software: you can redistribute it and/or modify
hudakz 0:e076052bcffd 16 it under the terms of the GNU General Public License as published by
hudakz 0:e076052bcffd 17 the Free Software Foundation, either version 3 of the License, or
hudakz 0:e076052bcffd 18 (at your option) any later version.
hudakz 0:e076052bcffd 19
hudakz 0:e076052bcffd 20 This program is distributed in the hope that it will be useful,
hudakz 0:e076052bcffd 21 but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 0:e076052bcffd 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 0:e076052bcffd 23 GNU General Public License for more details.
hudakz 0:e076052bcffd 24
hudakz 0:e076052bcffd 25 You should have received a copy of the GNU General Public License
hudakz 0:e076052bcffd 26 along with this program. If not, see <http://www.gnu.org/licenses/>.
hudakz 0:e076052bcffd 27 */
hudakz 0:e076052bcffd 28 /*
hudakz 0:e076052bcffd 29 * This library implements Manchester code using UART serial connection. Each
hudakz 0:e076052bcffd 30 * data byte is encoded into two bytes representing two nibbles of the original
hudakz 0:e076052bcffd 31 * data byte. These two bytes are then sent over UART serial link connection.
hudakz 0:e076052bcffd 32 * The receiver reconstructs the original data byte from the two bytes received.
hudakz 0:e076052bcffd 33 * A start and stop pattern are sent to signify the begin and end of a message.
hudakz 0:e076052bcffd 34 *
hudakz 0:e076052bcffd 35 * The library is based on the article published by Adrian Mills:
hudakz 0:e076052bcffd 36 * http://www.quickbuilder.co.uk/qb/articles/Manchester_encoding_using_RS232.pdf
hudakz 0:e076052bcffd 37 */
hudakz 0:e076052bcffd 38
hudakz 0:e076052bcffd 39 #include "ManchesterUART.h"
hudakz 0:e076052bcffd 40 #include "ManchesterMsg.h"
hudakz 0:e076052bcffd 41
hudakz 0:e076052bcffd 42 /**
hudakz 0:e076052bcffd 43 * @brief Transmits message
hudakz 0:e076052bcffd 44 * @note
hudakz 0:e076052bcffd 45 * @param msg Message to transmit
hudakz 0:e076052bcffd 46 * @retval
hudakz 0:e076052bcffd 47 */
hudakz 0:e076052bcffd 48 void ManchesterUART::transmit(ManchesterMsg& msg) {
hudakz 0:e076052bcffd 49 _data = msg.data;
hudakz 0:e076052bcffd 50 _len = msg.len;
hudakz 0:e076052bcffd 51
hudakz 0:e076052bcffd 52 _serial.putc(START);
hudakz 0:e076052bcffd 53 for (uint32_t i = 0; i < _len; i++) {
hudakz 0:e076052bcffd 54 transmitByte(_data[i]);
hudakz 0:e076052bcffd 55 }
hudakz 0:e076052bcffd 56 _serial.putc(STOP);
hudakz 0:e076052bcffd 57 }
hudakz 0:e076052bcffd 58
hudakz 0:e076052bcffd 59 /**
hudakz 0:e076052bcffd 60 * @brief Transmits a byte
hudakz 0:e076052bcffd 61 * @note
hudakz 0:e076052bcffd 62 * @param data The byte to transmit
hudakz 0:e076052bcffd 63 * @retval
hudakz 0:e076052bcffd 64 */
hudakz 0:e076052bcffd 65 void ManchesterUART::transmitByte(uint8_t data) {
hudakz 0:e076052bcffd 66 uint8_t encoded;
hudakz 0:e076052bcffd 67
hudakz 0:e076052bcffd 68 for (uint8_t i = 0; i < 2; i++) {
hudakz 0:e076052bcffd 69 encoded = 0; // manchester encoded byte
hudakz 0:e076052bcffd 70 for (uint8_t j = 0; j < 4; j++) {
hudakz 0:e076052bcffd 71 encoded >>= 2;
hudakz 0:e076052bcffd 72 if (data & 0b00000001)
hudakz 0:e076052bcffd 73 encoded |= 0b01000000; // 1->0
hudakz 0:e076052bcffd 74 else
hudakz 0:e076052bcffd 75 encoded |= 0b10000000; // 0->1
hudakz 0:e076052bcffd 76 data >>= 1;
hudakz 0:e076052bcffd 77 }
hudakz 0:e076052bcffd 78 _serial.putc(encoded);
hudakz 0:e076052bcffd 79 }
hudakz 0:e076052bcffd 80 }
hudakz 0:e076052bcffd 81
hudakz 0:e076052bcffd 82 /**
hudakz 0:e076052bcffd 83 * @brief Receives message
hudakz 0:e076052bcffd 84 * @note Waits until a message is received or error occured
hudakz 0:e076052bcffd 85 * @param msg Container to store the received message in
hudakz 0:e076052bcffd 86 * @retval true On success
hudakz 0:e076052bcffd 87 * false Otherwise
hudakz 0:e076052bcffd 88 */
hudakz 0:e076052bcffd 89 bool ManchesterUART::receive(ManchesterMsg& msg) {
hudakz 0:e076052bcffd 90 uint8_t recvByte1, recvByte2;
hudakz 0:e076052bcffd 91
hudakz 0:e076052bcffd 92 _error = NO_ERROR;
hudakz 0:e076052bcffd 93 _data = msg.data;
hudakz 0:e076052bcffd 94 _len = 0;
hudakz 0:e076052bcffd 95 _maxLen = msg.maxLen();
hudakz 0:e076052bcffd 96 _timeout.attach(callback(this, &ManchesterUART::rxTimeout), _timeout_sec);
hudakz 0:e076052bcffd 97
hudakz 0:e076052bcffd 98 do {
hudakz 0:e076052bcffd 99 recvByte1 = _serial.getc();
hudakz 0:e076052bcffd 100 if (_error) {
hudakz 0:e076052bcffd 101 if (_error != RX_TIMEOUT)
hudakz 0:e076052bcffd 102 _timeout.detach();
hudakz 0:e076052bcffd 103 msg.len = 0;
hudakz 0:e076052bcffd 104 return false;
hudakz 0:e076052bcffd 105 }
hudakz 0:e076052bcffd 106 } while (recvByte1 != START); // wait for START pattern
hudakz 0:e076052bcffd 107
hudakz 0:e076052bcffd 108
hudakz 0:e076052bcffd 109 while (true) {
hudakz 0:e076052bcffd 110 recvByte1 = _serial.getc();
hudakz 0:e076052bcffd 111 if (recvByte1 == STOP)
hudakz 0:e076052bcffd 112 break;
hudakz 0:e076052bcffd 113 if (_len > _maxLen - 1) {
hudakz 0:e076052bcffd 114 _error = BUF_OVERRUN;
hudakz 0:e076052bcffd 115 break;
hudakz 0:e076052bcffd 116 }
hudakz 0:e076052bcffd 117
hudakz 0:e076052bcffd 118 recvByte2 = _serial.getc();
hudakz 0:e076052bcffd 119 if (recvByte2 == STOP) {
hudakz 0:e076052bcffd 120 _error = ILLEGAL_CODE;
hudakz 0:e076052bcffd 121 break;
hudakz 0:e076052bcffd 122 }
hudakz 0:e076052bcffd 123 _data[_len++] = (getNibble(recvByte1)) | (getNibble(recvByte2) << 4);
hudakz 0:e076052bcffd 124 if (_error)
hudakz 0:e076052bcffd 125 break;
hudakz 0:e076052bcffd 126 }
hudakz 0:e076052bcffd 127
hudakz 0:e076052bcffd 128 if (_error != RX_TIMEOUT)
hudakz 0:e076052bcffd 129 _timeout.detach();
hudakz 0:e076052bcffd 130
hudakz 0:e076052bcffd 131 if (_error) {
hudakz 0:e076052bcffd 132 msg.len = 0;
hudakz 0:e076052bcffd 133 return false;
hudakz 0:e076052bcffd 134 }
hudakz 0:e076052bcffd 135 else {
hudakz 0:e076052bcffd 136 msg.len = _len;
hudakz 0:e076052bcffd 137 return true;
hudakz 0:e076052bcffd 138 }
hudakz 0:e076052bcffd 139 }
hudakz 0:e076052bcffd 140
hudakz 0:e076052bcffd 141 /**
hudakz 0:e076052bcffd 142 * @brief ISR handling 'reception timeout'
hudakz 0:e076052bcffd 143 * @note Called when receiving a message takes longer than limit.
hudakz 0:e076052bcffd 144 * Signals 'timeout error' by setting error flag.
hudakz 0:e076052bcffd 145 * @param
hudakz 0:e076052bcffd 146 * @retval
hudakz 0:e076052bcffd 147 */
hudakz 0:e076052bcffd 148 void ManchesterUART::rxTimeout(void) {
hudakz 0:e076052bcffd 149 _timeout.detach();
hudakz 0:e076052bcffd 150 _error = RX_TIMEOUT;
hudakz 0:e076052bcffd 151 }
hudakz 0:e076052bcffd 152
hudakz 0:e076052bcffd 153 /**
hudakz 0:e076052bcffd 154 * @brief Gets a nibble of received byte
hudakz 0:e076052bcffd 155 * @note Checks for illegal codes/patterns
hudakz 0:e076052bcffd 156 * @param nibble A byte received over UART (Manchester encoded nibble)
hudakz 0:e076052bcffd 157 * @retval Decoded nibble
hudakz 0:e076052bcffd 158 */
hudakz 0:e076052bcffd 159 uint8_t ManchesterUART::getNibble(uint8_t encoded) {
hudakz 0:e076052bcffd 160 uint8_t decoded, pattern;
hudakz 0:e076052bcffd 161
hudakz 0:e076052bcffd 162 decoded = 0;
hudakz 0:e076052bcffd 163 for (int i = 0; i < 4; i++) {
hudakz 0:e076052bcffd 164 decoded >>= 1;
hudakz 0:e076052bcffd 165 pattern = encoded & 0b11;
hudakz 0:e076052bcffd 166 if (pattern == 0b1) // 1
hudakz 0:e076052bcffd 167 decoded |= (0b01 << 3);
hudakz 0:e076052bcffd 168 else
hudakz 0:e076052bcffd 169 if (pattern == 0b10) // 0
hudakz 0:e076052bcffd 170 decoded &= ~(0b1 << 3);
hudakz 0:e076052bcffd 171 else {
hudakz 0:e076052bcffd 172 _error = ILLEGAL_CODE;
hudakz 0:e076052bcffd 173 break;
hudakz 0:e076052bcffd 174 }
hudakz 0:e076052bcffd 175 encoded >>= 2;
hudakz 0:e076052bcffd 176 }
hudakz 0:e076052bcffd 177
hudakz 0:e076052bcffd 178 return decoded;
hudakz 0:e076052bcffd 179 }
hudakz 0:e076052bcffd 180