Manchester code (phase encoding) library.

Dependents:   Manchester_Transmitter Manchester_Receiver

Manchester code (phase encoding) library

It implements Manchester code according to both IEEE 802.3 and G.E. Thomas' conventions.

  • A '0' is expressed by a high-to-low transition, a '1' by low-to-high transition in the IEEE 802.3 convention. The reverse is true in the G.E. Thomas' convention.
  • The transitions which signify '0' or '1' occur at the midpoint of a period.
  • Transitions at the start of a period are overhead and don't signify data.
  • Least significant bit is sent first
  • There are synchronization pulses (the number can be set) at the begin of transmission

    Select a convention to be used by commenting or uncommenting the line below in the Manchester.h header file.

Manchester.h

#define G_E_THOMAS 1

The IEEE 802.3 convention is used by default.

A Manchester encoded message (using G.E. Thomas' convention), with one sync pulse in the preamble, carrying four bytes:

/media/uploads/hudakz/manchester01.png

ACKNOWLEDGEMENT: The code in this library was based on this article published by Robert Guastella.

Import programManchester_Transmitter

Manchester transmitter demo.


Import programManchester_Receiver

Manchester receiver demo.

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

Revision:
2:de778df5892c
Parent:
1:11292d238e50
Child:
3:03109c995123
--- a/Manchester.cpp	Wed May 17 08:17:13 2017 +0000
+++ b/Manchester.cpp	Wed May 17 21:02:49 2017 +0000
@@ -2,7 +2,7 @@
  ******************************************************************************
  * @file    Manchester.cpp
  * @author  Zoltan Hudak
- * @version 
+ * @version
  * @date    16-May-2017
  * @brief   Manchester code for mbed
  ******************************************************************************
@@ -25,7 +25,6 @@
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-  
 #include "Manchester.h"
 #include "ManchesterMsg.h"
 
@@ -35,17 +34,12 @@
  * @param   txPin Pin name of transmitter line
  *          rxPin Pin name of receiver line
  *          speed Communication bit rate in bits per second
- *          tol   Pulse width tolerance (+/-) in %
+ *          tol Pulse width tolerance in %
  * @retval
  */
-Manchester::Manchester
-    (
-        PinName     txPin, 
-        PinName     rxPin, 
-        uint32_t    speed   /* = 1200 bps */, 
-        uint8_t     tol     /* = 20% */ 
-    ) :
-    _tx(txPin), _rx(rxPin) {
+Manchester::Manchester(PinName txPin, PinName rxPin, uint32_t speed /* = 1200 bps */, uint8_t tol /* = 20% */ ) :
+    _tx(txPin),
+    _rx(rxPin) {
     _state = IDLE;
     _midBitTime = 1000000 / speed / 2;  // mid-bit time [us]
     _minPulseWidth = (_midBitTime * 2 * (100 - tol)) / 100; // [us]
@@ -87,9 +81,11 @@
  */
 void Manchester::transmission(void) {
     static uint8_t  encodeByte;
-    static uint32_t byteIndex;
+    static size_t   byteIndex;
     static uint8_t  bitIndex;
 
+    _timeout.attach_us(callback(this, &Manchester::txTimeout), _maxPulseWidth * 4);
+
     switch(_state) {
     case SYNCH_START:
         _tx = 0;            // pull the line low to start synch pulse
@@ -101,7 +97,7 @@
         break;
 
     case SYNCH_END:
-        _tx = 1;            // bring line hight for end of sych pulse
+        _tx = 1;            // bring line high for end of sych pulse
         byteIndex = 0;
         encodeByte = _data[byteIndex];
         bitIndex = 0;
@@ -117,7 +113,7 @@
         break;
 
     case TRANSITION:
-        _tx = (encodeByte & 0x01) ^ 0x01;  // set line appropriately for transition
+        _tx = (encodeByte & 0x01) ^ 0x01;       // set line appropriately for transition
         if(++bitIndex < 8) {
             encodeByte = (encodeByte >> 1);
             _state = SETUP;
@@ -134,19 +130,33 @@
         break;
 
     case COMPLETE:
-        _tx = 1;    // transition is complete, bring line high
+        _tx = 1;    // transmission is complete, bring line high
         _state = IDLE;
         break;
 
     case IDLE:
     default:
+        _timeout.detach();
         return;
     }
 }
 
 /**
+ * @brief   ISR handling 'transmission timeout'
+ * @note    Called when transmitter is stuck.
+ *          Signals 'end of transmission' by setting state to IDLE
+ * @param   None
+ * @retval  None
+ */
+void Manchester::txTimeout(void) {
+    _timeout.detach();
+    _state = IDLE;
+}
+
+/**
  * @brief   Receives message
- * @note
+ * @note    Waits until a message is received
+ *          or receive timeout occured
  * @param   msg   Container to store the received message
  * @retval  true  On success
  *          false Otherwise
@@ -186,8 +196,8 @@
 }
 
 /**
- * @brief   ISR to handle reception
- * @note    Called on signal rise or fall on receiver line 
+ * @brief   ISR handling reception
+ * @note    Called on signal change (rise or fall) on receiver line
  * @param
  * @retval
  */
@@ -198,29 +208,28 @@
     static uint8_t  decodeByte;
     static uint8_t  bitIndex;
 
+    _timeout.attach_us(callback(this, &Manchester::rxTimeout), _maxPulseWidth * 4);
+
     switch(_state) {
     case LISTEN:
         begin = now;
-        if(_rx == 0) {
+        if(_rx == 0)
             _state = SYNCH_START;
-            _rxTimeout.attach_us(callback(this, &Manchester::rxTimeout), _maxPulseWidth * 2);
-        }
         else
             _state = ERROR;
         break;
 
     case SYNCH_START:
         pulseWidth = now - begin;
-        if((pulseWidth > _maxPulseWidth) | (_rx == 0))
-            _state = ERROR;
-        else {
+        if((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth) && (_rx == 1)) {
             begin = now;
             decodeByte = 0;
+            bitIndex = 0;
             _len = 0;
-            bitIndex = 0;
             _state = DECODE;
-            _rxTimeout.attach_us(callback(this, &Manchester::rxTimeout), _maxPulseWidth * 2);
         }
+        else
+            _state = ERROR; // It isn't a synch pulse => error
         break;
 
     case DECODE:
@@ -239,35 +248,32 @@
             }
         }
 
-        if(pulseWidth > _maxPulseWidth) {
-            _state = ERROR;
-        }
-        else
-            _rxTimeout.attach_us(callback(this, &Manchester::rxTimeout), _maxPulseWidth * 2);
+        if(pulseWidth > _maxPulseWidth)
+            _state = ERROR; // Pulse width out of limit => error
 
         break;
 
     case IDLE:
     case ERROR:
     default:
+        _timeout.detach();
         break;
     }
 }
 
 /**
- * @brief   ISR to handle receive timeout
- * @note    Signals end of transmission by setting state to IDLE
- *          or timeout error by setting state to ERROR.
+ * @brief   ISR handling 'receive timeout'
+ * @note    Called when receiver line rxPin is idle longer than limit.
+ *          Signals 'end of transmission' by setting state to IDLE
+ *          or 'timeout error' by setting state to ERROR.
  * @param   None
  * @retval  None
  */
 void Manchester::rxTimeout(void) {
-    _rxTimeout.detach();
+    _timeout.detach();
 
-    if(_state == DECODE)
+    if((_state == DECODE) && (_rx == 1))
         _state = IDLE;  // End of transmission
     else
         _state = ERROR; // Incomplete transmission
 }
-
-