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.
Dependents: ManchesterUART_Transmitter ManchesterUART_Receiver
ManchesterUART.cpp
- Committer:
- hudakz
- Date:
- 2017-11-22
- Revision:
- 0:e076052bcffd
- Child:
- 1:b869674fe56e
File content as of revision 0:e076052bcffd:
/*
******************************************************************************
* @file ManchesterUART.cpp
* @author Zoltan Hudak
* @version
* @date 2017-Nov-22
* @brief Manchester code over UART for mbed
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 Zoltan Hudak <hudakz@outlook.com>
*
* All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This library implements Manchester code using UART serial connection. Each
* data byte is encoded into two bytes representing two nibbles of the original
* data byte. These two bytes are then sent over UART serial link connection.
* The receiver reconstructs the original data byte from the two bytes received.
* A start and stop pattern are sent to signify the begin and end of a message.
*
* The library is based on the article published by Adrian Mills:
* http://www.quickbuilder.co.uk/qb/articles/Manchester_encoding_using_RS232.pdf
*/
#include "ManchesterUART.h"
#include "ManchesterMsg.h"
/**
* @brief Transmits message
* @note
* @param msg Message to transmit
* @retval
*/
void ManchesterUART::transmit(ManchesterMsg& msg) {
_data = msg.data;
_len = msg.len;
_serial.putc(START);
for (uint32_t i = 0; i < _len; i++) {
transmitByte(_data[i]);
}
_serial.putc(STOP);
}
/**
* @brief Transmits a byte
* @note
* @param data The byte to transmit
* @retval
*/
void ManchesterUART::transmitByte(uint8_t data) {
uint8_t encoded;
for (uint8_t i = 0; i < 2; i++) {
encoded = 0; // manchester encoded byte
for (uint8_t j = 0; j < 4; j++) {
encoded >>= 2;
if (data & 0b00000001)
encoded |= 0b01000000; // 1->0
else
encoded |= 0b10000000; // 0->1
data >>= 1;
}
_serial.putc(encoded);
}
}
/**
* @brief Receives message
* @note Waits until a message is received or error occured
* @param msg Container to store the received message in
* @retval true On success
* false Otherwise
*/
bool ManchesterUART::receive(ManchesterMsg& msg) {
uint8_t recvByte1, recvByte2;
_error = NO_ERROR;
_data = msg.data;
_len = 0;
_maxLen = msg.maxLen();
_timeout.attach(callback(this, &ManchesterUART::rxTimeout), _timeout_sec);
do {
recvByte1 = _serial.getc();
if (_error) {
if (_error != RX_TIMEOUT)
_timeout.detach();
msg.len = 0;
return false;
}
} while (recvByte1 != START); // wait for START pattern
while (true) {
recvByte1 = _serial.getc();
if (recvByte1 == STOP)
break;
if (_len > _maxLen - 1) {
_error = BUF_OVERRUN;
break;
}
recvByte2 = _serial.getc();
if (recvByte2 == STOP) {
_error = ILLEGAL_CODE;
break;
}
_data[_len++] = (getNibble(recvByte1)) | (getNibble(recvByte2) << 4);
if (_error)
break;
}
if (_error != RX_TIMEOUT)
_timeout.detach();
if (_error) {
msg.len = 0;
return false;
}
else {
msg.len = _len;
return true;
}
}
/**
* @brief ISR handling 'reception timeout'
* @note Called when receiving a message takes longer than limit.
* Signals 'timeout error' by setting error flag.
* @param
* @retval
*/
void ManchesterUART::rxTimeout(void) {
_timeout.detach();
_error = RX_TIMEOUT;
}
/**
* @brief Gets a nibble of received byte
* @note Checks for illegal codes/patterns
* @param nibble A byte received over UART (Manchester encoded nibble)
* @retval Decoded nibble
*/
uint8_t ManchesterUART::getNibble(uint8_t encoded) {
uint8_t decoded, pattern;
decoded = 0;
for (int i = 0; i < 4; i++) {
decoded >>= 1;
pattern = encoded & 0b11;
if (pattern == 0b1) // 1
decoded |= (0b01 << 3);
else
if (pattern == 0b10) // 0
decoded &= ~(0b1 << 3);
else {
_error = ILLEGAL_CODE;
break;
}
encoded >>= 2;
}
return decoded;
}