Manchester
Diff: Manchester.cpp
- Revision:
- 8:c1b5893191fe
- Parent:
- 7:afd0ee36dcd1
- Child:
- 9:7a23184aa9ef
--- a/Manchester.cpp Sun Sep 03 09:04:18 2017 +0000
+++ b/Manchester.cpp Sun Oct 14 09:38:33 2018 +0000
@@ -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/>.
*/
-
/*
This library implements Manchester code according to both IEEE 802.3
and G.E. Thomas' conventions.
@@ -40,7 +39,6 @@
Select a convention to be used by commenting or uncommenting
the line "#define G_E_THOMAS 1" in the Manchester.h header file.
*/
-
#include "Manchester.h"
#include "ManchesterMsg.h"
@@ -54,21 +52,29 @@
* @retval
*/
Manchester::Manchester
- (
- PinName txPin,
- PinName rxPin,
- uint32_t speed, /* = 1200 bps */
- uint8_t tol /* = (+/-)25% */
- ) :
+(
+ PinName txPin,
+ PinName rxPin,
+ uint32_t baudrate, /* = 1200 bps */
+ uint8_t tol, /* = (+/-)25% */
+ float rxTimeout /* = 5s */
+) :
_tx(txPin),
- _rx(rxPin) {
+ _rx(rxPin)
+{
_state = IDLE;
- _midBitTime = 1000000 / speed / 2; // mid-bit time [us]
+ _midBitTime = 1000000 / baudrate / 2; // mid-bit time [us]
_minPulseWidth = (_midBitTime * 2 * (100 - tol)) / 100; // [us]
_maxPulseWidth = (_midBitTime * 2 * (100 + tol)) / 100; // [us]
+ _rxTimeout = rxTimeout;
_rx.disable_irq();
_rx.rise(callback(this, &Manchester::reception));
_rx.fall(callback(this, &Manchester::reception));
+ _preamble = 8; // number of synch_start patterns
+ _error = "no error";
+ // printf("_midBitTime = %d\r\n", _midBitTime);
+ // printf("_minPulseWidth = %d\r\n", _minPulseWidth);
+ // printf("_maxPulseWidth = %d\r\n", _maxPulseWidth);
#ifdef G_E_THOMAS
_tx = 1;
#else
@@ -82,7 +88,8 @@
* @param msg Message to transmit
* @retval
*/
-void Manchester::transmit(ManchesterMsg& msg) {
+void Manchester::transmit(ManchesterMsg& msg)
+{
bool txFinished;
_data = msg.data;
@@ -94,7 +101,7 @@
core_util_critical_section_enter();
txFinished = (_state == IDLE);
core_util_critical_section_exit();
- } while(!txFinished);
+ } while (!txFinished);
_txTicker.detach();
}
@@ -105,82 +112,124 @@
* @param
* @retval
*/
-void Manchester::transmission(void) {
+void Manchester::transmission(void)
+{
static uint8_t encodeByte;
static size_t byteIndex;
static uint8_t bitIndex;
+ static uint8_t counter;
- _timeout.attach_us(callback(this, &Manchester::txTimeout), _maxPulseWidth * 4);
+ _timeout.attach_us(callback(this, &Manchester::onTxTimeout), _maxPulseWidth * 4);
- switch(_state) {
- case SYNCH_START:
-#ifdef G_E_THOMAS
- _tx = 0; // pull line low to start synch pulse
-#else
- _tx = 1; // bring line high to start synch pulse
-#endif
- _state = SYNCH_NEXT;
- break;
+ switch (_state)
+ {
+ case SYNCH_START:
+ if (_preamble == 0)
+ {
+ byteIndex = 0;
+ encodeByte = _data[byteIndex];
+ bitIndex = 0;
+ _state = SETUP;
+ break;
+ }
- case SYNCH_NEXT:
- _state = SYNCH_END; // synch pulse needs to be twice the interrupt rate
- break;
+ #ifdef G_E_THOMAS
+ _tx = 0; // pull line low to start synch pulse
+ #else
+ _tx = 1; // bring line high to start synch pulse
+ #endif
+ counter = 0;
+ _state = SYNCH_NEXT;
+ break;
- case SYNCH_END:
-#ifdef G_E_THOMAS
- _tx = 1; // bring line high for end of sych pulse
-#else
- _tx = 0; // pull line low for end of sych pulse
-#endif
- byteIndex = 0;
- encodeByte = _data[byteIndex];
- bitIndex = 0;
- _state = SETUP;
- break;
+ case SYNCH_NEXT:
+ counter++;
+ if ((counter % 4) == 0)
+ _tx = !_tx;
+ if (counter < (_preamble * 8))
+ break;
+ else
+ {
+ byteIndex = 0;
+ encodeByte = _data[byteIndex];
+ bitIndex = 0;
+ _state = SETUP;
+ break;
+ }
- case SETUP:
-#ifdef G_E_THOMAS
- _tx = encodeByte & 0x01; // setup for next bit to transmit
-#else
- _tx = !(encodeByte & 0x01); // setup for next bit to transmit
-#endif
- _state = TRANSITION;
- break;
+ case SETUP:
+ #ifdef G_E_THOMAS
+ _tx = encodeByte & 0x01; // setup for next bit to transmit
+ #else
+ _tx = !(encodeByte & 0x01); // setup for next bit to transmit
+ #endif
+ _state = TRANSITION;
+ break;
- case TRANSITION:
-#ifdef G_E_THOMAS
- _tx = !(encodeByte & 0x01); // set line appropriately for transition
-#else
- _tx = encodeByte & 0x01; // set line appropriately for transition
-#endif
- if(++bitIndex < 8) {
- encodeByte = (encodeByte >> 1);
- _state = SETUP;
- }
- else {
- if(++byteIndex < _len) {
- encodeByte = _data[byteIndex];
+ case TRANSITION:
+ #ifdef G_E_THOMAS
+ _tx = !(encodeByte & 0x01); // set line appropriately for transition
+ #else
+ _tx = encodeByte & 0x01; // set line appropriately for transition
+ #endif
+ if (++bitIndex < 8)
+ {
+ encodeByte = (encodeByte >> 1);
_state = SETUP;
- bitIndex = 0;
}
else
- _state = COMPLETE;
- }
- break;
+ {
+ if (++byteIndex < _len)
+ {
+ encodeByte = _data[byteIndex];
+ _state = SETUP;
+ bitIndex = 0;
+ }
+ else
+ {
+ counter = 0;
+ _state = STOP;
+ }
+ }
+ break;
- case COMPLETE:
-#ifdef G_E_THOMAS
- _tx = 1; // transmission is complete, bring line high
-#else
- _tx = 0; // transmission is complete, pull line low
-#endif
- _state = IDLE;
- break;
+ case STOP:
+ counter++;
+ if (counter == 1)
+ {
+ #ifdef G_E_THOMAS
+ _tx = 1;
+ #else
+ _tx = 0;
+ #endif
+ }
+ else
+ if (counter == 5)
+ {
+ #ifdef G_E_THOMAS
+ _tx = 0;
+ #else
+ _tx = 1;
+ #endif
+ }
+ else
+ if (counter == 8)
+ _state = COMPLETE;
+ break;
- case IDLE:
- default:
- _timeout.detach();
- return;
+ case COMPLETE:
+ #ifdef G_E_THOMAS
+ _tx = 1;
+ #else
+ _tx = 0;
+ #endif
+ _state = IDLE;
+ break;
+
+ case IDLE:
+ default:
+ _timeout.detach();
+ return;
}
}
@@ -191,7 +240,8 @@
* @param
* @retval
*/
-void Manchester::txTimeout(void) {
+void Manchester::onTxTimeout(void)
+{
_timeout.detach();
_state = IDLE;
}
@@ -203,29 +253,34 @@
* @retval true On success
* false Otherwise
*/
-bool Manchester::receive(ManchesterMsg& msg) {
- bool rxFinished;
+bool Manchester::receive(ManchesterMsg& msg)
+{
+ bool rxFinished;
_data = msg.data;
_maxLen = msg.maxLen();
_state = LISTEN;
-
+ _timeout.attach(callback(this, &Manchester::onRxTimeout), _rxTimeout);
_rx.enable_irq();
do {
core_util_critical_section_enter();
rxFinished = ((_state == IDLE) || (_state == ERROR));
core_util_critical_section_exit();
- } while(!rxFinished);
+ } while (!rxFinished);
_rx.disable_irq();
+ _timer.stop();
+ _timeout.detach();
- if(_state == ERROR) {
+ if (_state == ERROR)
+ {
msg.len = 0;
_state = IDLE;
return false;
}
- else {
+ else
+ {
msg.len = _len;
return true;
}
@@ -237,75 +292,136 @@
* @param
* @retval
*/
-void Manchester::reception(void) {
+void Manchester::reception(void)
+{
uint32_t now = us_ticker_read();
static uint32_t begin;
uint32_t pulseWidth;
static uint8_t decodeByte;
static uint8_t bitIndex;
- _timeout.attach_us(callback(this, &Manchester::rxTimeout), _maxPulseWidth * 4);
-
- switch(_state) {
- case LISTEN:
- begin = now;
-#ifdef G_E_THOMAS
- if(_rx == 0)
-#else
- if(_rx == 1)
-#endif
- _state = SYNCH_START;
- else
- _state = ERROR; // It isn't a synch pulse => error
- break;
-
- case SYNCH_START:
- pulseWidth = now - begin;
-#ifdef G_E_THOMAS
- if((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth) && (_rx == 1)) {
-#else
- if((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth) && (_rx == 0)) {
-#endif
+ switch (_state)
+ {
+ case LISTEN:
begin = now;
- decodeByte = 0;
- bitIndex = 0;
- _len = 0;
- _state = DECODE;
- }
- else
- _state = ERROR; // It isn't a synch pulse => error
- break;
+ if (
+ #ifdef G_E_THOMAS
+ _rx == 0
+ #else
+ _rx == 1
+ #endif
+ )
+ {
+ _state = SYNCH_START;
+ }
+ else
+ {
+ _error = "SYNCH_START: Isn't a SYNCH pulse";
+ _state = ERROR;
+ }
+ break;
+
+ case SYNCH_START:
+ pulseWidth = now - begin;
+ //printf("%d <= %d <= %d\r\n", (_midBitTime * 2) + _minPulseWidth, pulseWidth, (_midBitTime * 2) + _maxPulseWidth);
+ if (((_midBitTime * 2) + _minPulseWidth <= pulseWidth) && (pulseWidth <= (_midBitTime * 2) + _maxPulseWidth))
+ {
+ begin = now;
+ _state = SYNCH_NEXT;
+ }
+ else
+ {
+ _error = "SYNCH_START: Isn't a SYNCH pulse";
+ _state = ERROR;
+ }
+ break;
- case DECODE:
- pulseWidth = now - begin;
- if((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth)) {
- begin = now;
-#ifdef G_E_THOMAS
- decodeByte |= (((_rx == 0) & 0x01) << bitIndex++);
-#else
- decodeByte |= (((_rx == 1) & 0x01) << bitIndex++);
-#endif
- if(bitIndex > 7) {
- _data[_len++] = decodeByte;
- if(_len > _maxLen - 1)
- _state = ERROR;
- else {
- decodeByte = 0;
- bitIndex = 0;
+ case SYNCH_NEXT:
+ pulseWidth = now - begin;
+ //printf("%d <= %d <= %d\r\n", (_midBitTime * 2) + _minPulseWidth, pulseWidth, (_midBitTime * 2) + _maxPulseWidth);
+ if (((_midBitTime * 2) + _minPulseWidth <= pulseWidth) && (pulseWidth <= (_midBitTime * 2) + _maxPulseWidth))
+ {
+ begin = now;
+ _state = SYNCH_NEXT;
+ }
+ else
+ if ((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth))
+ {
+ begin = now;
+ decodeByte = 0;
+ bitIndex = 0;
+ _len = 0;
+ #ifdef G_E_THOMAS
+ decodeByte |= (((_rx == 0) & 0x01) << bitIndex++);
+ #else
+ decodeByte |= (((_rx == 1) & 0x01) << bitIndex++);
+ #endif
+ _state = DECODE;
+ }
+ break;
+
+ case DECODE:
+ pulseWidth = now - begin;
+ if ((_minPulseWidth <= pulseWidth) && (pulseWidth <= _maxPulseWidth))
+ {
+ begin = now;
+ #ifdef G_E_THOMAS
+ decodeByte |= (((_rx == 0) & 0x01) << bitIndex++);
+ #else
+ decodeByte |= (((_rx == 1) & 0x01) << bitIndex++);
+ #endif
+ if (bitIndex > 7)
+ {
+ _data[_len++] = decodeByte;
+ if (_len > _maxLen - 1)
+ _state = ERROR;
+ else
+ {
+ decodeByte = 0;
+ bitIndex = 0;
+ }
+ }
+ break;
+ }
+
+ if (pulseWidth > _maxPulseWidth)
+ {
+ if (
+ #ifdef G_E_THOMAS
+ _rx == 0
+ #else
+ _rx == 1
+ #endif
+ )
+ {
+ begin = now;
+ _state = COMPLETE; // End of reception
}
}
- }
-
- if(pulseWidth > _maxPulseWidth)
- _state = ERROR; // Pulse width out of limit => error
+ break;
- break;
+ case COMPLETE:
+ pulseWidth = now - begin;
+ if (pulseWidth > _maxPulseWidth)
+ {
+ if (
+ #ifdef G_E_THOMAS
+ _rx == 1
+ #else
+ _rx == 0
+ #endif
+ )
+ {
+ _state = IDLE; // End of reception
+ }
+ }
+ break;
- case IDLE:
- case ERROR:
- default:
- _timeout.detach();
- break;
+ case IDLE:
+ case ERROR:
+ default:
+ _timeout.detach();
+ break;
}
}
@@ -317,15 +433,22 @@
* @param
* @retval
*/
-void Manchester::rxTimeout(void) {
+void Manchester::onRxTimeout(void)
+{
_timeout.detach();
#ifdef G_E_THOMAS
- if((_state == DECODE) && (_rx == 1))
+ if ((_state == DECODE) && (_rx == 1))
#else
- if((_state == DECODE) && (_rx == 0))
+ if ((_state == DECODE) && (_rx == 0))
#endif
- _state = IDLE; // Reception successful
- else
- _state = ERROR; // Reception incomplete
+ {
+ _error = "rx timeout";
+ _state = IDLE; // Reception successful
+ }
+ else
+ {
+ _error = "reception error";
+ _state = ERROR; // Reception incomplete
+ }
}