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.

Revision:
1:b869674fe56e
Parent:
0:e076052bcffd
Child:
2:8cb6a0a77e56
--- a/ManchesterUART.cpp	Wed Nov 22 16:37:13 2017 +0000
+++ b/ManchesterUART.cpp	Mon Jul 30 09:38:03 2018 +0000
@@ -26,16 +26,15 @@
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 /*
- * This library implements Manchester code using UART serial connection. Each 
+ * 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. 
+ * 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 
+ * http://www.quickbuilder.co.uk/qb/articles/Manchester_encoding_using_RS232.pdf
  */
- 
 #include "ManchesterUART.h"
 #include "ManchesterMsg.h"
 
@@ -45,14 +44,18 @@
  * @param   msg Message to transmit
  * @retval
  */
-void ManchesterUART::transmit(ManchesterMsg& msg) {
+void ManchesterUART::transmit(ManchesterMsg& msg)
+{
     _data = msg.data;
     _len = msg.len;
 
-    _serial.putc(START);
-    for (uint32_t i = 0; i < _len; i++) {
+    for (uint8_t i = 0; i < _preamble; i++)
+        _serial.putc(START);
+    for (uint32_t i = 0; i < _len; i++)
+    {
         transmitByte(_data[i]);
     }
+
     _serial.putc(STOP);
 }
 
@@ -62,12 +65,15 @@
  * @param   data The byte to transmit
  * @retval
  */
-void ManchesterUART::transmitByte(uint8_t data) {
+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++) {
+    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
@@ -75,6 +81,7 @@
                 encoded |= 0b10000000;  // 0->1
             data >>= 1;
         }
+
         _serial.putc(encoded);
     }
 }
@@ -86,53 +93,86 @@
  * @retval  true  On success
  *          false Otherwise
  */
-bool ManchesterUART::receive(ManchesterMsg& msg) {
-    uint8_t recvByte1, recvByte2;
-
+bool ManchesterUART::receive(ManchesterMsg& msg)
+{
+    uint8_t byte1, byte2;
+    bool    byte1Received;
+    
     _error = NO_ERROR;
     _data = msg.data;
     _len = 0;
     _maxLen = msg.maxLen();
-    _timeout.attach(callback(this, &ManchesterUART::rxTimeout), _timeout_sec);
+    
+    if (!_serial.readable())
+        return false;
 
+    _timeout.attach(callback(this, &ManchesterUART::rxTimeout), _rxTimeout);
+    
+    //
+    // wait for START pattern
     do {
-        recvByte1 = _serial.getc();
-        if (_error) {
+        byte1 = _serial.getc();
+        if (_error)
+        {
+            if (_error != RX_TIMEOUT)
+                _timeout.detach();
+            msg.len = 0;
+            return false;
+        }
+    } while (byte1 != START);
+    //
+    // read START pattern
+    do {
+        byte1 = _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;
+    } while (byte1 == START);
+
+    byte1Received = true;   // byte1 available from the loop above
+
+    while (true)
+    {
+        if (byte1Received)
+            byte1Received = false;
+        else
+        {
+            byte1 = _serial.getc();
+            if (byte1 == STOP)
+                break;
+            if (_len > _maxLen - 1)
+            {
+                _error = BUF_OVERRUN;
+                break;
+            }
+        }
+
+        byte2 = _serial.getc();
+        if (byte2 == STOP)
+        {
+            _error = ILLEGAL_CODE;
             break;
         }
-        
-        recvByte2 = _serial.getc();
-        if (recvByte2 == STOP) {
-            _error = ILLEGAL_CODE;
+
+        _data[_len++] = (getNibble(byte1)) | (getNibble(byte2) << 4);
+        if (_error)
             break;
-        }        
-        _data[_len++] = (getNibble(recvByte1)) | (getNibble(recvByte2) << 4);               
-        if (_error)
-            break;           
     }
-        
+
     if (_error != RX_TIMEOUT)
         _timeout.detach();
 
-    if (_error) {
+    if (_error)
+    {
         msg.len = 0;
         return false;
     }
-    else {
+    else
+    {
         msg.len = _len;
         return true;
     }
@@ -145,7 +185,8 @@
  * @param
  * @retval
  */
-void ManchesterUART::rxTimeout(void) {
+void ManchesterUART::rxTimeout(void)
+{
     _timeout.detach();
     _error = RX_TIMEOUT;
 }
@@ -153,28 +194,31 @@
 /**
  * @brief   Gets a nibble of received byte
  * @note    Checks for illegal codes/patterns
- * @param   nibble A byte received over UART (Manchester encoded nibble)
+ * @param   nibble  A byte received over UART (Manchester encoded nibble)
  * @retval  Decoded nibble
  */
-uint8_t ManchesterUART::getNibble(uint8_t encoded) {
+uint8_t ManchesterUART::getNibble(uint8_t encoded)
+{
     uint8_t decoded, pattern;
 
     decoded = 0;
-    for (int i = 0; i < 4; i++) {
+    for (int i = 0; i < 4; i++)
+    {
         decoded >>= 1;
-        pattern = encoded & 0b11;
-        if (pattern == 0b1)    // 1
-            decoded |= (0b01 << 3);
+        pattern = encoded & 0b000011;
+        if (pattern == 0b00000001)  // 1
+            decoded |= (0b00000001 << 3);
         else
-        if (pattern == 0b10)    // 0
-            decoded &= ~(0b1 << 3);
-        else {
+        if (pattern == 0b00000010)  // 0
+            decoded &= ~(0b00000001 << 3);
+        else
+        {
             _error = ILLEGAL_CODE;
             break;
         }
+
         encoded >>= 2;
     }
-    
+
     return decoded;
 }
-