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 theManchester.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:
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.
Diff: Manchester.cpp
- Revision:
- 2:de778df5892c
- Parent:
- 1:11292d238e50
- Child:
- 3:03109c995123
diff -r 11292d238e50 -r de778df5892c Manchester.cpp --- 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 } - -