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 Oct 17 16:16:34 2018 +0000
Revision:
2:8cb6a0a77e56
Parent:
1:b869674fe56e
Number of start patterns in preamble can be set.

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 1:b869674fe56e 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 1:b869674fe56e 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 1:b869674fe56e 34 *
hudakz 0:e076052bcffd 35 * The library is based on the article published by Adrian Mills:
hudakz 1:b869674fe56e 36 * http://www.quickbuilder.co.uk/qb/articles/Manchester_encoding_using_RS232.pdf
hudakz 0:e076052bcffd 37 */
hudakz 0:e076052bcffd 38 #include "ManchesterUART.h"
hudakz 0:e076052bcffd 39 #include "ManchesterMsg.h"
hudakz 0:e076052bcffd 40
hudakz 0:e076052bcffd 41 /**
hudakz 0:e076052bcffd 42 * @brief Transmits message
hudakz 0:e076052bcffd 43 * @note
hudakz 0:e076052bcffd 44 * @param msg Message to transmit
hudakz 0:e076052bcffd 45 * @retval
hudakz 0:e076052bcffd 46 */
hudakz 1:b869674fe56e 47 void ManchesterUART::transmit(ManchesterMsg& msg)
hudakz 1:b869674fe56e 48 {
hudakz 0:e076052bcffd 49 _data = msg.data;
hudakz 0:e076052bcffd 50 _len = msg.len;
hudakz 0:e076052bcffd 51
hudakz 1:b869674fe56e 52 for (uint8_t i = 0; i < _preamble; i++)
hudakz 1:b869674fe56e 53 _serial.putc(START);
hudakz 1:b869674fe56e 54 for (uint32_t i = 0; i < _len; i++)
hudakz 1:b869674fe56e 55 {
hudakz 0:e076052bcffd 56 transmitByte(_data[i]);
hudakz 0:e076052bcffd 57 }
hudakz 1:b869674fe56e 58
hudakz 0:e076052bcffd 59 _serial.putc(STOP);
hudakz 0:e076052bcffd 60 }
hudakz 0:e076052bcffd 61
hudakz 0:e076052bcffd 62 /**
hudakz 0:e076052bcffd 63 * @brief Transmits a byte
hudakz 0:e076052bcffd 64 * @note
hudakz 0:e076052bcffd 65 * @param data The byte to transmit
hudakz 0:e076052bcffd 66 * @retval
hudakz 0:e076052bcffd 67 */
hudakz 1:b869674fe56e 68 void ManchesterUART::transmitByte(uint8_t data)
hudakz 1:b869674fe56e 69 {
hudakz 0:e076052bcffd 70 uint8_t encoded;
hudakz 0:e076052bcffd 71
hudakz 1:b869674fe56e 72 for (uint8_t i = 0; i < 2; i++)
hudakz 1:b869674fe56e 73 {
hudakz 1:b869674fe56e 74 encoded = 0; // manchester encoded byte
hudakz 1:b869674fe56e 75 for (uint8_t j = 0; j < 4; j++)
hudakz 1:b869674fe56e 76 {
hudakz 0:e076052bcffd 77 encoded >>= 2;
hudakz 0:e076052bcffd 78 if (data & 0b00000001)
hudakz 0:e076052bcffd 79 encoded |= 0b01000000; // 1->0
hudakz 0:e076052bcffd 80 else
hudakz 0:e076052bcffd 81 encoded |= 0b10000000; // 0->1
hudakz 0:e076052bcffd 82 data >>= 1;
hudakz 0:e076052bcffd 83 }
hudakz 1:b869674fe56e 84
hudakz 0:e076052bcffd 85 _serial.putc(encoded);
hudakz 0:e076052bcffd 86 }
hudakz 0:e076052bcffd 87 }
hudakz 0:e076052bcffd 88
hudakz 0:e076052bcffd 89 /**
hudakz 0:e076052bcffd 90 * @brief Receives message
hudakz 0:e076052bcffd 91 * @note Waits until a message is received or error occured
hudakz 0:e076052bcffd 92 * @param msg Container to store the received message in
hudakz 0:e076052bcffd 93 * @retval true On success
hudakz 0:e076052bcffd 94 * false Otherwise
hudakz 0:e076052bcffd 95 */
hudakz 1:b869674fe56e 96 bool ManchesterUART::receive(ManchesterMsg& msg)
hudakz 1:b869674fe56e 97 {
hudakz 1:b869674fe56e 98 uint8_t byte1, byte2;
hudakz 1:b869674fe56e 99 bool byte1Received;
hudakz 1:b869674fe56e 100
hudakz 0:e076052bcffd 101 _error = NO_ERROR;
hudakz 0:e076052bcffd 102 _data = msg.data;
hudakz 0:e076052bcffd 103 _len = 0;
hudakz 0:e076052bcffd 104 _maxLen = msg.maxLen();
hudakz 1:b869674fe56e 105
hudakz 1:b869674fe56e 106 if (!_serial.readable())
hudakz 1:b869674fe56e 107 return false;
hudakz 0:e076052bcffd 108
hudakz 1:b869674fe56e 109 _timeout.attach(callback(this, &ManchesterUART::rxTimeout), _rxTimeout);
hudakz 1:b869674fe56e 110
hudakz 1:b869674fe56e 111 //
hudakz 1:b869674fe56e 112 // wait for START pattern
hudakz 0:e076052bcffd 113 do {
hudakz 1:b869674fe56e 114 byte1 = _serial.getc();
hudakz 1:b869674fe56e 115 if (_error)
hudakz 1:b869674fe56e 116 {
hudakz 1:b869674fe56e 117 if (_error != RX_TIMEOUT)
hudakz 1:b869674fe56e 118 _timeout.detach();
hudakz 1:b869674fe56e 119 msg.len = 0;
hudakz 1:b869674fe56e 120 return false;
hudakz 1:b869674fe56e 121 }
hudakz 1:b869674fe56e 122 } while (byte1 != START);
hudakz 1:b869674fe56e 123 //
hudakz 1:b869674fe56e 124 // read START pattern
hudakz 1:b869674fe56e 125 do {
hudakz 1:b869674fe56e 126 byte1 = _serial.getc();
hudakz 1:b869674fe56e 127 if (_error)
hudakz 1:b869674fe56e 128 {
hudakz 0:e076052bcffd 129 if (_error != RX_TIMEOUT)
hudakz 0:e076052bcffd 130 _timeout.detach();
hudakz 0:e076052bcffd 131 msg.len = 0;
hudakz 0:e076052bcffd 132 return false;
hudakz 0:e076052bcffd 133 }
hudakz 1:b869674fe56e 134 } while (byte1 == START);
hudakz 1:b869674fe56e 135
hudakz 1:b869674fe56e 136 byte1Received = true; // byte1 available from the loop above
hudakz 1:b869674fe56e 137
hudakz 1:b869674fe56e 138 while (true)
hudakz 1:b869674fe56e 139 {
hudakz 1:b869674fe56e 140 if (byte1Received)
hudakz 1:b869674fe56e 141 byte1Received = false;
hudakz 1:b869674fe56e 142 else
hudakz 1:b869674fe56e 143 {
hudakz 1:b869674fe56e 144 byte1 = _serial.getc();
hudakz 1:b869674fe56e 145 if (byte1 == STOP)
hudakz 1:b869674fe56e 146 break;
hudakz 1:b869674fe56e 147 if (_len > _maxLen - 1)
hudakz 1:b869674fe56e 148 {
hudakz 1:b869674fe56e 149 _error = BUF_OVERRUN;
hudakz 1:b869674fe56e 150 break;
hudakz 1:b869674fe56e 151 }
hudakz 1:b869674fe56e 152 }
hudakz 1:b869674fe56e 153
hudakz 1:b869674fe56e 154 byte2 = _serial.getc();
hudakz 1:b869674fe56e 155 if (byte2 == STOP)
hudakz 1:b869674fe56e 156 {
hudakz 1:b869674fe56e 157 _error = ILLEGAL_CODE;
hudakz 0:e076052bcffd 158 break;
hudakz 0:e076052bcffd 159 }
hudakz 1:b869674fe56e 160
hudakz 1:b869674fe56e 161 _data[_len++] = (getNibble(byte1)) | (getNibble(byte2) << 4);
hudakz 1:b869674fe56e 162 if (_error)
hudakz 0:e076052bcffd 163 break;
hudakz 0:e076052bcffd 164 }
hudakz 1:b869674fe56e 165
hudakz 0:e076052bcffd 166 if (_error != RX_TIMEOUT)
hudakz 0:e076052bcffd 167 _timeout.detach();
hudakz 0:e076052bcffd 168
hudakz 1:b869674fe56e 169 if (_error)
hudakz 1:b869674fe56e 170 {
hudakz 0:e076052bcffd 171 msg.len = 0;
hudakz 0:e076052bcffd 172 return false;
hudakz 0:e076052bcffd 173 }
hudakz 1:b869674fe56e 174 else
hudakz 1:b869674fe56e 175 {
hudakz 0:e076052bcffd 176 msg.len = _len;
hudakz 0:e076052bcffd 177 return true;
hudakz 0:e076052bcffd 178 }
hudakz 0:e076052bcffd 179 }
hudakz 0:e076052bcffd 180
hudakz 0:e076052bcffd 181 /**
hudakz 0:e076052bcffd 182 * @brief ISR handling 'reception timeout'
hudakz 0:e076052bcffd 183 * @note Called when receiving a message takes longer than limit.
hudakz 0:e076052bcffd 184 * Signals 'timeout error' by setting error flag.
hudakz 0:e076052bcffd 185 * @param
hudakz 0:e076052bcffd 186 * @retval
hudakz 0:e076052bcffd 187 */
hudakz 1:b869674fe56e 188 void ManchesterUART::rxTimeout(void)
hudakz 1:b869674fe56e 189 {
hudakz 0:e076052bcffd 190 _timeout.detach();
hudakz 0:e076052bcffd 191 _error = RX_TIMEOUT;
hudakz 0:e076052bcffd 192 }
hudakz 0:e076052bcffd 193
hudakz 0:e076052bcffd 194 /**
hudakz 0:e076052bcffd 195 * @brief Gets a nibble of received byte
hudakz 0:e076052bcffd 196 * @note Checks for illegal codes/patterns
hudakz 1:b869674fe56e 197 * @param nibble A byte received over UART (Manchester encoded nibble)
hudakz 0:e076052bcffd 198 * @retval Decoded nibble
hudakz 0:e076052bcffd 199 */
hudakz 1:b869674fe56e 200 uint8_t ManchesterUART::getNibble(uint8_t encoded)
hudakz 1:b869674fe56e 201 {
hudakz 0:e076052bcffd 202 uint8_t decoded, pattern;
hudakz 0:e076052bcffd 203
hudakz 0:e076052bcffd 204 decoded = 0;
hudakz 1:b869674fe56e 205 for (int i = 0; i < 4; i++)
hudakz 1:b869674fe56e 206 {
hudakz 0:e076052bcffd 207 decoded >>= 1;
hudakz 1:b869674fe56e 208 pattern = encoded & 0b000011;
hudakz 1:b869674fe56e 209 if (pattern == 0b00000001) // 1
hudakz 1:b869674fe56e 210 decoded |= (0b00000001 << 3);
hudakz 0:e076052bcffd 211 else
hudakz 1:b869674fe56e 212 if (pattern == 0b00000010) // 0
hudakz 1:b869674fe56e 213 decoded &= ~(0b00000001 << 3);
hudakz 1:b869674fe56e 214 else
hudakz 1:b869674fe56e 215 {
hudakz 0:e076052bcffd 216 _error = ILLEGAL_CODE;
hudakz 0:e076052bcffd 217 break;
hudakz 0:e076052bcffd 218 }
hudakz 1:b869674fe56e 219
hudakz 0:e076052bcffd 220 encoded >>= 2;
hudakz 0:e076052bcffd 221 }
hudakz 1:b869674fe56e 222
hudakz 0:e076052bcffd 223 return decoded;
hudakz 0:e076052bcffd 224 }
hudakz 2:8cb6a0a77e56 225