diff --git a/source/TransceiverConfig.hpp b/source/TransceiverConfig.hpp
index f1d3f455f5a04612a8e02dcd38f4948ce93278eb..15985616cf05ffa2866f959503e37bf799d476bb 100644
--- a/source/TransceiverConfig.hpp
+++ b/source/TransceiverConfig.hpp
@@ -31,22 +31,22 @@ namespace com_saxbophone {
          * @brief Pulses longer than this duration are ignored for decoding.
          * @details This is set to 100000µs (100ms)
          */
-        const static unsigned long MAXIMUM_PULSE_DURATION = 100000;
+        const static unsigned long MAXIMUM_PULSE_DURATION = 500000;
 
         /**
          * @brief STOP/START bits are useful for demarcating when a transmission
          * begins and ends.
          * @details This is set to 42000µs (42ms)
          */
-        const static unsigned long STOP_START_BIT_DURATION = 42000;
-        const static unsigned long STOP_START_BIT_DURATION_MS = 42;
+        const static unsigned long STOP_START_BIT_DURATION = 200000;
+        const static unsigned long STOP_START_BIT_DURATION_MS = 200;
 
         /**
          * @brief This is the duration of a standard raw bit on the signal line.
          * @details This is set to 24000µs (24ms)
          */
-        const static unsigned long SIGNAL_BIT_DURATION = 24000;
-        const static unsigned long SIGNAL_BIT_DURATION_MS = 24;
+        const static unsigned long SIGNAL_BIT_DURATION = 100000;
+        const static unsigned long SIGNAL_BIT_DURATION_MS = 100;
 
         /**
          * @brief This is the margin of error we allow for when deciding what
@@ -54,7 +54,7 @@ namespace com_saxbophone {
          * @note 1.0 = 100% and 0.0 = 0%
          * @details We currently allow a ±10% timing margin
          */
-        constexpr const static double DURATION_MARGIN = 0.1;
+        constexpr const static double DURATION_MARGIN = 0.25;
 
         /**
          * @brief This is the total amount of time allocated for one transmission
@@ -62,7 +62,7 @@ namespace com_saxbophone {
          * silence time for good measure. This is set to 600ms.
          * @note This is the only duration in this struct to use ms for units
          */
-        const static unsigned long TRANSMISSION_WINDOW = 600;
+        const static unsigned long TRANSMISSION_WINDOW = 2000;
     };
 
 };
diff --git a/source/main.cpp b/source/main.cpp
index ad71a8e6cbd173c8ebe54ee9eba34702b7193ff9..385e450e188cdf95e10b444ef8e263dea8b26106 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -81,11 +81,11 @@ public:
      * @brief Attempt to pair with another connected micro:bit
      * @param my_role Whether we wish to be the Master or Slave for comms
      * purposes
-     * @returns true if paired successfully
-     * @returns false if unable to pair successfully
+     * @returns 0 if paired successfully
+     * @returns error code number if unable to pair successfully
      * @note This is a blocking call!
      */
-    bool attempt_pair(Role my_role) {
+    int attempt_pair(Role my_role) {
         if (my_role == Role::MASTER) {
             // attempt pair as Master
             return this->pair_as_master();
@@ -94,7 +94,7 @@ public:
             return this->pair_as_slave();
         } else {
             // invalid Role!
-            return false;
+            return -1;
         }
     }
 
@@ -122,7 +122,7 @@ public:
     }
 
 private:
-    bool pair_as_master() {
+    int pair_as_master() {
         int pin_state = ubit.io.pin[COMMS_PIN_NUMBER].getDigitalValue();
         // clarify if someone else is driving the pin HI or if pin is invalid
         switch (pin_state) {
@@ -136,52 +136,52 @@ private:
              * been configured with a pin that can't do Digital I/O. In either
              * case, this is a failure condition.
              */
-            return false;
+            return 2;
         }
         // successful execution continues here
         // wait for the pin to stay LO for 500ms
         unsigned long start_time, end_time;
         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) return false;
+        if (pin_state != 0) return 4;
         // there's definitely no-one else transmitting on the line, now we transmit
         this->busy_wait_drive_pin(500, start_time, end_time);
         // end_time is the clock synchronisation timestamp
         this->synchronisation_timestamp = end_time;
-        // now, wait up to 100ms for a reply from the Slave
-        this->busy_wait_on_pin(0, 100, pin_state, start_time, end_time);
+        // now, wait up to 200ms for a reply from the Slave
+        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) return false;
-        // now, Slave should keep the Line HI for at least 450ms
-        this->busy_wait_on_pin(1, 450, pin_state, start_time, end_time);
+        if (pin_state != 1) return 6;
+        // 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
-        if (pin_state == 0) return false;
-        // otherwise, pin is still HI --allow Slave up to 100ms to bring it LO
-        this->busy_wait_on_pin(1, 100, pin_state, start_time, end_time);
+        if (pin_state == 0) 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);
         // if the pin is still HI, then Slave drove the pin for too long
-        if (pin_state == 1) return false;
+        if (pin_state == 1) return 10;
         // otherwise, all we need to do now is to wait for synchronisation
         return this->await_synchronisation();
     }
 
-    bool pair_as_slave() {
+    int pair_as_slave() {
         // check the pin can read digital values
         int pin_state = ubit.io.pin[COMMS_PIN_NUMBER].getDigitalValue();
-        if (pin_state == MICROBIT_NOT_SUPPORTED) return false; // oh no, it can't
+        if (pin_state == MICROBIT_NOT_SUPPORTED) return 1; // oh no, it can't
         // otherwise, it can read digital values
         // now, wait up to 10000ms for Master to drive the line HI
         unsigned long start_time, end_time;
         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) return false; // we timed out
-        // otherwise, line is HI, wait for it to stay that way at least 450ms
-        this->busy_wait_on_pin(1, 450, pin_state, start_time, end_time);
+        if (pin_state != 1) 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);
         // clarify the loop ended because timeout occurred (pin should be HI)
-        if (pin_state != 1) return false; // pin went LO, that's not correct
-        // wait up to 100 more ms for line to go LO
-        this->busy_wait_on_pin(1, 100, pin_state, start_time, end_time);
+        if (pin_state != 1) 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);
         // if line is still HI, then it's overrun
-        if (pin_state == 1) return false;
+        if (pin_state == 1) return 7;
         // otherwise, it's now our turn to bring the line HI
         // the most recent end_time is also the sync point, store that first
         this->synchronisation_timestamp = end_time;
@@ -270,16 +270,16 @@ private:
      * @warn Don't call this if this->synchronisation_timestamp hasn't been set
      * first!
      */
-    bool await_synchronisation() {
+    int await_synchronisation() {
         // calculate synchronisation time and check it's in the future
         unsigned long sync_time = this->synchronisation_timestamp + 2500;
         unsigned long now_time = ubit.systemTime();
-        if (sync_time < now_time) return false; // can't do it, sync point in past
+        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
         do {
             now_time = ubit.systemTime();
         } while (now_time < sync_time);
-        return true; // at this point, now both Master and Slave are synchronised
+        return 0; // at this point, now both Master and Slave are synchronised
     }
 
     unsigned long synchronisation_timestamp;
@@ -617,7 +617,7 @@ void morse_checker() {
         if (morse_decoder.remove_next(current)) { // if we could read another Morse code
             // current has now updated, so display this new char
             if (current != previous) {
-                ubit.display.printCharAsync(current);
+                ubit.display.printChar(current);
             }
             // whenever another character is removed, send it down the line
             /*
@@ -625,13 +625,14 @@ void morse_checker() {
              * they will be encoded rather than sent raw
              */
             manchester_encoder.input(current); // NOTE: Might need cast
+            ubit.display.clear();
         } else {
             // otherwise, peek into what the code appears to be thus far
             char peek = morse_decoder.peek();
             // if this peek is different to what it previously was, display
             if (peek != current) {
                 current = peek;
-                ubit.display.printCharAsync(current);
+                ubit.display.printChar(current);
             }
         }
     }
@@ -641,7 +642,7 @@ void morse_checker() {
 // simple fiber that simply passes data out of encoder and into the line driver
 void flush_output() {
     while (true) {
-        ubit.sleep(100); // yield the CPU for a bit
+        ubit.sleep(10); // yield the CPU for a bit
         int next_state = 0;
         while (manchester_encoder.get_next_state(next_state)) {
             line_driver.input(next_state);
@@ -653,7 +654,7 @@ void flush_output() {
 // simple fiber that simply flushes data out of line monitor and into decoder
 void flush_input() {
     while (true) {
-        ubit.sleep(100); // yield the CPU for a bit
+        ubit.sleep(10); // yield the CPU for a bit
         line_monitor.flush();
     }
 }
@@ -666,11 +667,7 @@ int main() {
     // greyscale mode please!
     ubit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);
 
-    // create one fiber --this infinitely checks the decoder and outputs changes
-    create_fiber(morse_checker);
     // these lightweight fibers ferry data to and from decoders and line stuff
-    create_fiber(flush_output);
-    create_fiber(flush_input);
 
     // this is the main program loop, an infinite while!
     while (true) {
@@ -680,19 +677,17 @@ int main() {
         Pairer pairer;
 
         // try to pair and if unsuccessful, go back to top of loop to restart
-        if (not pairer.attempt_pair(my_role)) {
+        int error_code = pairer.attempt_pair(my_role);
+        if (error_code != 0) {
             // scroll "PF" to indicate "PAIR FAILURE"
             ubit.display.scroll("PF");
+            ubit.display.scroll(error_code);
             continue; // skip back to start of loop body to re-try pair
         }
         // otherwise, if execution continues here then we're paired
 
         // for now, we only act on button presses if we're the Master
         if (my_role == Role::MASTER) {
-            // initialise the ButtonTracker
-            button_tracker.init();
-            // enable the morse checker!
-            morse_checker_enabled = true;
             // scroll "PM" to mean "PAIRED MASTER"
             ubit.display.scroll("PM");
         } else if (my_role == Role::SLAVE) {
@@ -703,6 +698,14 @@ int main() {
         /* BEGIN COMMS */
 
         if (my_role == Role::MASTER) { // Master's comms loop
+            // initialise the ButtonTracker
+            button_tracker.init();
+            // create one fiber --this infinitely checks the decoder and outputs changes
+            create_fiber(morse_checker);
+            // enable the morse checker!
+            morse_checker_enabled = true;
+            create_fiber(flush_output);
+            // line_driver.init();
             while (true) { // TODO: consider what exit conditions can be used
                 // call barrier to synchronise both master and slave
                 pairer.barrier();
@@ -710,10 +713,16 @@ int main() {
                 line_driver.flush();
             }
         } else { // Slave's comms loop
+            create_fiber(flush_input);
+            line_monitor.init();
             while (true) { // TODO: consider what exit conditions can be used
                 // call barrier to synchronise both master and slave
                 pairer.barrier();
                 // TODO: display the output?
+                uint8_t next_byte = 0x00u;
+                if (manchester_decoder.get_next_byte(next_byte)) {
+                    ubit.display.scrollAsync((int)next_byte);
+                }
             }
         }