Manchester

Files at this revision

API Documentation at this revision

Comitter:
hudakz
Date:
Wed May 17 21:02:49 2017 +0000
Parent:
1:11292d238e50
Child:
3:03109c995123
Commit message:
Updated.

Changed in this revision

Manchester.cpp Show annotated file Show diff for this revision Revisions of this file
Manchester.h Show annotated file Show diff for this revision Revisions of this file
ManchesterMsg.h Show annotated file Show diff for this revision Revisions of this file
--- 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
 }
-
-
--- a/Manchester.h	Wed May 17 08:17:13 2017 +0000
+++ b/Manchester.h	Wed May 17 21:02:49 2017 +0000
@@ -2,7 +2,7 @@
  ******************************************************************************
  * @file    Manchester.h
  * @author  Zoltan Hudak
- * @version 
+ * @version
  * @date    16-May-2017
  * @brief   Manchester code for mbed
  ******************************************************************************
@@ -25,7 +25,7 @@
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
- 
+
 #ifndef MANCHESTER_H
 #define MANCHESTER_H
 
@@ -47,35 +47,37 @@
         DECODE,
         ERROR
     };
-    
+
 public:
     Manchester
     (
         PinName     txPin,          /* transmitter pin name */
         PinName     rxPin,          /* receiver pin name */
-        uint32_t    speed = 1200    /* speed in bits per second */, 
-        uint8_t     tol = 20        /* pulse width tolerance (+/-) in % */ 
+        uint32_t    speed = 1200    /* speed in bits per second */,
+        uint8_t     tol = 20        /* pulse width tolerance (+/-) in % */
     );
-    ~Manchester(void) { };
+    ~Manchester(void) { }
     void    transmit(ManchesterMsg& msg);
     bool    receive(ManchesterMsg& msg);
-    
+
 private:
     DigitalOut  _tx;            // transmitter line
     InterruptIn _rx;            // receiver line
     Ticker      _txTicker;      // transmitter ticker
-    Timeout     _rxTimeout;     // receiver timeout
+    Timeout     _timeout;       // timeout (watchdog)
     uint32_t    _midBitTime;    // mid-bit time [us]
     uint32_t    _minPulseWidth; // minimum pulse width [us]
     uint32_t    _maxPulseWidth; // maximum pulse width [us]
     State       _state;         // state
     char*       _data;          // data array
-    uint8_t     _len;           // data length in bytes
-    uint8_t     _maxLen;        // maximum length
-    
+    size_t      _len;           // data length in bytes
+    size_t      _maxLen;        // maximum length
+
     void        transmission(void);
     void        reception(void);
+    void        txTimeout(void);
     void        rxTimeout(void);
 };
 #endif // MANCHESTER_H
 
+
--- a/ManchesterMsg.h	Wed May 17 08:17:13 2017 +0000
+++ b/ManchesterMsg.h	Wed May 17 21:02:49 2017 +0000
@@ -2,7 +2,7 @@
  ******************************************************************************
  * @file    ManchesterMsg.h
  * @author  Zoltan Hudak
- * @version 
+ * @version
  * @date    16-May-2017
  * @brief   Message container
  ******************************************************************************
@@ -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/>.
  */
-  
 #ifndef MANCHESTERMSG_H
 #define MANCHESTERMSG_H
 
@@ -35,42 +34,36 @@
  */
 class   ManchesterMsg
 {
-    unsigned char   _max;   // Max length (capacity) of data field in bytes
+    size_t  _max;   // Max length (capacity) of data field in bytes
 
 public:
-    char*           data;   // Data field
-    unsigned char   len;    // Length of data in bytes
+    char*   data;   // Data field
+    size_t  len;    // Length of data in bytes
 
     /** Creates empty Manchester message of specified capacity.
      */
-    ManchesterMsg(unsigned char max) :
-    _max(max),
-    data(new char[max])    { len = 0; }
+    ManchesterMsg(size_t max) : _max(max), data(new char[max]) { len = 0; }
 
-    ~ManchesterMsg(void)   { delete[] data; }
+    ~ ManchesterMsg(void)   { delete[] data; }
 
-     /** Copy constructor.
+    /** Copy constructor.
      */
-    ManchesterMsg(const ManchesterMsg& msg) {
-        len     = msg.len;
-        memcpy(data, msg.data, msg.len);
-    }
-   
-    
+    ManchesterMsg(const ManchesterMsg& msg) { len = msg.len; memcpy(data, msg.data, msg.len); }
+
     /** Returns message maximum length (capacity)
      */
-    unsigned char   maxLen(void)    { return _max; }
+    size_t  maxLen(void)    { return _max; }
 
     /** Clears message content
      */
-    void            clear(void)     { len = 0; memset(data, 0, _max); }
+    void    clear(void)     { len = 0; memset(data, 0, _max); }
 
     /** Inserter operator: Appends data (value) to Manchester message
      */
     template<class T>
     ManchesterMsg &operator<<(const T val) {
         if(len + sizeof(T) <= _max) {
-            *reinterpret_cast <T*> (&data[len]) = val;
+            *reinterpret_cast < T * > (&data[len]) = val;
             len += sizeof(T);
         }
 
@@ -85,10 +78,10 @@
     /** Inserter operator: Appends string of char to Manchester message
      */
     ManchesterMsg &operator<<(const char* str) {
-        unsigned char strLen = strlen(str);
+        size_t  strLen = strlen(str);
         if(len + strLen + 1 <= _max) {
             memcpy(data + len, (char*)str, strLen);
-            len += strLen; 
+            len += strLen;
             data[len++] = '\0';
         }
 
@@ -105,7 +98,7 @@
     template<class T>
     ManchesterMsg &operator>>(T& val) {
         if(sizeof(T) <= len) {
-            val = *reinterpret_cast <T*> (&data[0]);
+            val = *reinterpret_cast < T * > (&data[0]);
             len -= sizeof(T);
             memcpy(data, data + sizeof(T), len);
         }
@@ -117,10 +110,11 @@
 #endif
         return *this;
     }
+
     /** Extractor operator: Extracts string of char from CAN message
      */
     ManchesterMsg &operator>>(char* str) {
-        unsigned char strLen = strlen(data);
+        size_t  strLen = strlen(data);
         if(strLen <= len) {
             memcpy(str, data, strLen + 1);
             len -= (strLen + 1);