Library for Manchester encoding using UART's hardware.
Dependents: ManchesterUART_Transmitter ManchesterUART_Receiver
ManchesterUART.cpp
00001 /* 00002 ****************************************************************************** 00003 * @file ManchesterUART.cpp 00004 * @author Zoltan Hudak 00005 * @version 00006 * @date 2017-Nov-22 00007 * @brief Manchester code over UART for mbed 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2017 Zoltan Hudak <hudakz@outlook.com> 00012 * 00013 * All rights reserved. 00014 00015 This program is free software: you can redistribute it and/or modify 00016 it under the terms of the GNU General Public License as published by 00017 the Free Software Foundation, either version 3 of the License, or 00018 (at your option) any later version. 00019 00020 This program is distributed in the hope that it will be useful, 00021 but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 GNU General Public License for more details. 00024 00025 You should have received a copy of the GNU General Public License 00026 along with this program. If not, see <http://www.gnu.org/licenses/>. 00027 */ 00028 /* 00029 * This library implements Manchester code using UART serial connection. Each 00030 * data byte is encoded into two bytes representing two nibbles of the original 00031 * data byte. These two bytes are then sent over UART serial link connection. 00032 * The receiver reconstructs the original data byte from the two bytes received. 00033 * A start and stop pattern are sent to signify the begin and end of a message. 00034 * 00035 * The library is based on the article published by Adrian Mills: 00036 * http://www.quickbuilder.co.uk/qb/articles/Manchester_encoding_using_RS232.pdf 00037 */ 00038 #include "ManchesterUART.h" 00039 #include "ManchesterMsg.h" 00040 00041 /** 00042 * @brief Transmits message 00043 * @note 00044 * @param msg Message to transmit 00045 * @retval 00046 */ 00047 void ManchesterUART::transmit(ManchesterMsg& msg) 00048 { 00049 _data = msg.data; 00050 _len = msg.len; 00051 00052 for (uint8_t i = 0; i < _preamble; i++) 00053 _serial.putc(START); 00054 for (uint32_t i = 0; i < _len; i++) 00055 { 00056 transmitByte(_data[i]); 00057 } 00058 00059 _serial.putc(STOP); 00060 } 00061 00062 /** 00063 * @brief Transmits a byte 00064 * @note 00065 * @param data The byte to transmit 00066 * @retval 00067 */ 00068 void ManchesterUART::transmitByte(uint8_t data) 00069 { 00070 uint8_t encoded; 00071 00072 for (uint8_t i = 0; i < 2; i++) 00073 { 00074 encoded = 0; // manchester encoded byte 00075 for (uint8_t j = 0; j < 4; j++) 00076 { 00077 encoded >>= 2; 00078 if (data & 0b00000001) 00079 encoded |= 0b01000000; // 1->0 00080 else 00081 encoded |= 0b10000000; // 0->1 00082 data >>= 1; 00083 } 00084 00085 _serial.putc(encoded); 00086 } 00087 } 00088 00089 /** 00090 * @brief Receives message 00091 * @note Waits until a message is received or error occured 00092 * @param msg Container to store the received message in 00093 * @retval true On success 00094 * false Otherwise 00095 */ 00096 bool ManchesterUART::receive(ManchesterMsg& msg) 00097 { 00098 uint8_t byte1, byte2; 00099 bool byte1Received; 00100 00101 _error = NO_ERROR; 00102 _data = msg.data; 00103 _len = 0; 00104 _maxLen = msg.maxLen(); 00105 00106 if (!_serial.readable()) 00107 return false; 00108 00109 _timeout.attach(callback(this, &ManchesterUART::rxTimeout), _rxTimeout); 00110 00111 // 00112 // wait for START pattern 00113 do { 00114 byte1 = _serial.getc(); 00115 if (_error) 00116 { 00117 if (_error != RX_TIMEOUT) 00118 _timeout.detach(); 00119 msg.len = 0; 00120 return false; 00121 } 00122 } while (byte1 != START); 00123 // 00124 // read START pattern 00125 do { 00126 byte1 = _serial.getc(); 00127 if (_error) 00128 { 00129 if (_error != RX_TIMEOUT) 00130 _timeout.detach(); 00131 msg.len = 0; 00132 return false; 00133 } 00134 } while (byte1 == START); 00135 00136 byte1Received = true; // byte1 available from the loop above 00137 00138 while (true) 00139 { 00140 if (byte1Received) 00141 byte1Received = false; 00142 else 00143 { 00144 byte1 = _serial.getc(); 00145 if (byte1 == STOP) 00146 break; 00147 if (_len > _maxLen - 1) 00148 { 00149 _error = BUF_OVERRUN; 00150 break; 00151 } 00152 } 00153 00154 byte2 = _serial.getc(); 00155 if (byte2 == STOP) 00156 { 00157 _error = ILLEGAL_CODE; 00158 break; 00159 } 00160 00161 _data[_len++] = (getNibble(byte1)) | (getNibble(byte2) << 4); 00162 if (_error) 00163 break; 00164 } 00165 00166 if (_error != RX_TIMEOUT) 00167 _timeout.detach(); 00168 00169 if (_error) 00170 { 00171 msg.len = 0; 00172 return false; 00173 } 00174 else 00175 { 00176 msg.len = _len; 00177 return true; 00178 } 00179 } 00180 00181 /** 00182 * @brief ISR handling 'reception timeout' 00183 * @note Called when receiving a message takes longer than limit. 00184 * Signals 'timeout error' by setting error flag. 00185 * @param 00186 * @retval 00187 */ 00188 void ManchesterUART::rxTimeout(void) 00189 { 00190 _timeout.detach(); 00191 _error = RX_TIMEOUT; 00192 } 00193 00194 /** 00195 * @brief Gets a nibble of received byte 00196 * @note Checks for illegal codes/patterns 00197 * @param nibble A byte received over UART (Manchester encoded nibble) 00198 * @retval Decoded nibble 00199 */ 00200 uint8_t ManchesterUART::getNibble(uint8_t encoded) 00201 { 00202 uint8_t decoded, pattern; 00203 00204 decoded = 0; 00205 for (int i = 0; i < 4; i++) 00206 { 00207 decoded >>= 1; 00208 pattern = encoded & 0b000011; 00209 if (pattern == 0b00000001) // 1 00210 decoded |= (0b00000001 << 3); 00211 else 00212 if (pattern == 0b00000010) // 0 00213 decoded &= ~(0b00000001 << 3); 00214 else 00215 { 00216 _error = ILLEGAL_CODE; 00217 break; 00218 } 00219 00220 encoded >>= 2; 00221 } 00222 00223 return decoded; 00224 } 00225
Generated on Tue Jul 12 2022 21:49:11 by
![doxygen](doxygen.png)