From 836ffa16cf56bd2988f8e86ee5f77a8e7ae060b6 Mon Sep 17 00:00:00 2001 From: Joshua Saxby <Joshua2.Saxby@live.uwe.ac.uk> Date: Mon, 9 Mar 2020 12:57:26 +0000 Subject: [PATCH] Appeared to have eliminated bit-slip errors --- source/ManchesterDecoder.cpp | 7 ++++ source/ManchesterDecoder.hpp | 5 +++ source/main.cpp | 79 ++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/source/ManchesterDecoder.cpp b/source/ManchesterDecoder.cpp index 365c721..50a0bea 100644 --- a/source/ManchesterDecoder.cpp +++ b/source/ManchesterDecoder.cpp @@ -54,4 +54,11 @@ namespace com_saxbophone { this->buffer.shrink_from_front(1); return true; } + + void ManchesterDecoder::clear() { + this->buffer.clear(); + // also reset state variables + this->symbol_index = 0; + this->current_byte = 0x00u; + } }; diff --git a/source/ManchesterDecoder.hpp b/source/ManchesterDecoder.hpp index 0e10408..55e770e 100644 --- a/source/ManchesterDecoder.hpp +++ b/source/ManchesterDecoder.hpp @@ -55,6 +55,11 @@ namespace com_saxbophone { * @returns false if no bytes are available yet (destination is ignored) */ bool get_next_byte(uint8_t& destination); + + /** + * @brief Clears the input buffer, in case you want to do that. + */ + void clear(); private: /** * @brief Counter tracking how many "symbols" (i.e. boolean input states) diff --git a/source/main.cpp b/source/main.cpp index ba49722..14451b9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -51,7 +51,7 @@ MicroBit ubit; * @warn This method blocks until exactly one of button A or B is pressed! */ Role get_my_role() { - ubit.serial.send("get_my_role()"); + // ubit.serial.send("get_my_role()"); // scroll some stuff on the screen to prompt the user to choose ubit.display.scroll("<M"); // point left to Button A to choose Master ubit.sleep(100); // a brief pause @@ -108,18 +108,24 @@ public: */ void barrier() { // TODO: consider allowing for a ±10% margin of error - unsigned long time_now = ubit.systemTime(); // what time is it now? + unsigned long start_time = ubit.systemTime(); // what time is it now? // this is how much time we have left to next sync point unsigned long time_left = TransceiverConfig::TRANSMISSION_WINDOW - ( - (time_now - this->synchronisation_timestamp) % + (start_time - this->synchronisation_timestamp) % TransceiverConfig::TRANSMISSION_WINDOW ); + // calculate the time of the next sync point + unsigned long sync_point = start_time + time_left; /* * systemTime() can only sleep to 6ms resolution, so sleep to the nearest * multiple of 6ms, rounded down */ ubit.sleep((time_left / 6) * 6); - // TODO: consider adding busy-wait loop to increase accuracy + // busy wait loop sleeps for remainder of time + unsigned long time_now; + do { + time_now = ubit.systemTime(); + } while (time_now < sync_point); } private: @@ -137,7 +143,7 @@ private: * been configured with a pin that can't do Digital I/O. In either * case, this is a failure condition. */ - ubit.serial.send("MICROBIT_NOT_SUPPORTED\r\n"); + // ubit.serial.send("MICROBIT_NOT_SUPPORTED\r\n"); return 2; } // successful execution continues here @@ -146,7 +152,7 @@ private: this->busy_wait_on_pin(0, 500, pin_state, start_time, end_time); // check to make sure we didn't break out of the loop because of HI pin if (pin_state != 0) { - ubit.serial.send("Other Master on Line\r\n"); + // ubit.serial.send("Other Master on Line\r\n"); return 4; } // there's definitely no-one else transmitting on the line, now we transmit @@ -157,24 +163,24 @@ private: this->busy_wait_on_pin(0, 200, pin_state, start_time, end_time); // this time, check that the pin is HI --it must be HI, otherwise timeout if (pin_state != 1) { - ubit.serial.send("Timeout waiting for Slave\r\n"); + // ubit.serial.send("Timeout waiting for Slave\r\n"); return 6; } - ubit.serial.printf("Slave Latency: %i\r\n", end_time - start_time); + // ubit.serial.printf("Slave Latency: %i\r\n", end_time - start_time); // now, Slave should keep the Line HI for at least 400ms this->busy_wait_on_pin(1, 400, pin_state, start_time, end_time); // if the pin is LO, then Slave didn't drive it long enough - ubit.serial.printf("Slave Reply: %i\r\n", end_time - start_time); + // ubit.serial.printf("Slave Reply: %i\r\n", end_time - start_time); if (pin_state == 0) { - ubit.serial.send("Slave Reply too SHORT\r\n"); + // ubit.serial.send("Slave Reply too SHORT\r\n"); return 8; } // otherwise, pin is still HI --allow Slave up to 200ms to bring it LO this->busy_wait_on_pin(1, 200, pin_state, start_time, end_time); - ubit.serial.printf("Slave Reply: %i\r\n", end_time - start_time); + // ubit.serial.printf("Slave Reply: %i\r\n", end_time - start_time); // if the pin is still HI, then Slave drove the pin for too long if (pin_state == 1) { - ubit.serial.send("Slave Reply too LONG\r\n"); + // ubit.serial.send("Slave Reply too LONG\r\n"); return 10; } // otherwise, all we need to do now is to wait for synchronisation @@ -185,7 +191,7 @@ private: // check the pin can read digital values int pin_state = ubit.io.pin[COMMS_PIN_NUMBER].getDigitalValue(); if (pin_state == MICROBIT_NOT_SUPPORTED) { - ubit.serial.send("MICROBIT_NOT_SUPPORTED\r\n"); + // ubit.serial.send("MICROBIT_NOT_SUPPORTED\r\n"); return 1; } // oh no, it can't // otherwise, it can read digital values @@ -194,23 +200,23 @@ private: this->busy_wait_on_pin(0, 10000, pin_state, start_time, end_time); // clarify the loop ended because pin is now indeed HI if (pin_state != 1) { - ubit.serial.send("Timeout waiting for Master\r\n"); + // ubit.serial.send("Timeout waiting for Master\r\n"); return 3; } // we timed out // otherwise, line is HI, wait for it to stay that way at least 400ms this->busy_wait_on_pin(1, 400, pin_state, start_time, end_time); - ubit.serial.printf("Master Probe: %i\r\n", end_time - start_time); + // ubit.serial.printf("Master Probe: %i\r\n", end_time - start_time); // clarify the loop ended because timeout occurred (pin should be HI) if (pin_state != 1) { - ubit.serial.send("Master Probe too SHORT\r\n"); + // ubit.serial.send("Master Probe too SHORT\r\n"); return 5; } // pin went LO, that's not correct // wait up to 200 more ms for line to go LO this->busy_wait_on_pin(1, 200, pin_state, start_time, end_time); - ubit.serial.printf("Master Probe: %i\r\n", end_time - start_time); + // ubit.serial.printf("Master Probe: %i\r\n", end_time - start_time); // if line is still HI, then it's overrun if (pin_state == 1) { - ubit.serial.send("Master Probe too LONG\r\n"); + // ubit.serial.send("Master Probe too LONG\r\n"); return 7; } // otherwise, it's now our turn to bring the line HI @@ -304,7 +310,7 @@ private: int await_synchronisation() { // calculate synchronisation time and check it's in the future unsigned long sync_time = this->synchronisation_timestamp + 2500; - ubit.serial.printf("Sync Stamp: %i\r\n", sync_time); + // ubit.serial.printf("Sync Stamp: %i\r\n", sync_time); unsigned long now_time = ubit.systemTime(); if (sync_time < now_time) return 11; // can't do it, sync point in past // busy wait loop to wait until synchronisation time is reached @@ -491,14 +497,19 @@ public: * @brief Event-handler for input pin pulse HI or LO events */ void on_pulse(MicroBitEvent e) { - // only act on pulses which are shorter than a certain duration - if (e.timestamp > TransceiverConfig::MAXIMUM_PULSE_DURATION) return; // create a new Pulse and store it in the buffer Pulse p = { e.value == MICROBIT_PIN_EVT_PULSE_LO ? false : true, // state e.timestamp // duration }; - ubit.serial.printf("on_pulse() -> { %i, %lu, }\r\n", p.state, p.duration); + // if it's a long silence, this is a good time to clear input buffer + if (p.state == false and p.duration > TransceiverConfig::MAXIMUM_PULSE_DURATION) { + this->decoder.clear(); // this helps mitigate bit-slip errors persisting + // ubit.serial.send("Clear Buffer\r\n"); + } + // otherwise only act on pulses which are shorter than a certain duration + if (p.duration > TransceiverConfig::MAXIMUM_PULSE_DURATION) return; + // ubit.serial.printf("on_pulse() -> { %i, %lu, }\r\n", p.state, p.duration); this->buffer.add(p); } @@ -523,7 +534,7 @@ public: ) { // send two inputs of the given state has_output = true; - ubit.serial.printf("%d%d", p.state, p.state); + // ubit.serial.printf("%d%d", p.state, p.state); this->decoder.input(p.state); this->decoder.input(p.state); } else if ( @@ -535,12 +546,12 @@ public: ) { // send just one input of the given state has_output = true; - ubit.serial.printf("%d", p.state); + // ubit.serial.printf("%d", p.state); this->decoder.input(p.state); } } if (has_output) { - ubit.serial.send("<- MANCHEDECODE in\r\n"); + // ubit.serial.send("<- MANCHEDECODE in\r\n"); } // empty the buffer this->buffer.clear(); @@ -648,7 +659,7 @@ void morse_checker() { * NOTE: for now, just sending characters as-is but in the future * they will be encoded rather than sent raw */ - ubit.serial.printf("Morse Input: %d\r\n", (int)current); + // ubit.serial.printf("Morse Input: %c\r\n", current); manchester_encoder.input(current); // NOTE: Might need cast ubit.display.clear(); } else { @@ -672,11 +683,11 @@ void flush_output() { bool printed = false; while (manchester_encoder.get_next_state(next_state)) { printed = true; - ubit.serial.printf("%i", next_state); + // ubit.serial.printf("%i", next_state); line_driver.input(next_state); } if (printed) { - ubit.serial.send(" <- MANCHECODE out\r\n"); + // ubit.serial.send(" <- MANCHECODE out\r\n"); } } } @@ -720,11 +731,11 @@ int main() { // for now, we only act on button presses if we're the Master if (my_role == Role::MASTER) { // scroll "PM" to mean "PAIRED MASTER" - ubit.serial.send(" -> Role::MASTER\r\n"); + // ubit.serial.send(" -> Role::MASTER\r\n"); ubit.display.scroll("PM"); } else if (my_role == Role::SLAVE) { // scroll "PS" to mean "PAIRED SLAVE" - ubit.serial.send(" -> Role::SLAVE\r\n"); + // ubit.serial.send(" -> Role::SLAVE\r\n"); ubit.display.scroll("PS"); } @@ -750,13 +761,13 @@ int main() { line_monitor.init(); while (true) { // TODO: consider what exit conditions can be used // call barrier to synchronise both master and slave - // pairer.barrier(); - ubit.sleep(10); + pairer.barrier(); // TODO: display the output? uint8_t next_byte = 0x00u; if (manchester_decoder.get_next_byte(next_byte)) { - ubit.serial.printf("MANCHEDECODE -> %d\r\n", (int)next_byte); - ubit.display.printCharAsync(next_byte, 500); + // ubit.serial.printf("MANCHEDECODE -> %c\r\n", next_byte); + ubit.display.printChar(next_byte, 300); + ubit.display.clear(); } } } -- GitLab