From f87a087540b8a6fba8cee728e11861b7799645a7 Mon Sep 17 00:00:00 2001 From: Joshua Saxby <joshua.a.saxby@gmail.com> Date: Thu, 5 Mar 2020 18:47:51 +0000 Subject: [PATCH] Implemented Slave pair method This completes the pairing functionality --- source/main.cpp | 89 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index ded7c11..047622c 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -115,37 +115,12 @@ private: } // successful execution continues here // wait for the pin to stay LO for 500ms - unsigned long start_time = ubit.systemTime(); - unsigned long now_time = start_time; - do { - /* - * NOTE: this is a busy wait loop with no sleep() - * this is okay as we're deliberately allowing this function to - * block the entire system, it's documented as such and we also can - * only sleep to a 6ms precision, but we want to time as accurately - * as possible for the pairing process - */ - now_time = ubit.systemTime(); - pin_state = ubit.io.pin[COMMS_PIN_NUMBER].getDigitalValue(); - } while (pin_state == 0 and (now_time - start_time) < 500); + unsigned long start_time, now_time; + this->busy_wait_on_pin(0, 500, pin_state, start_time, now_time); // check to make sure we didn't break out of the loop because of HI pin if (pin_state != 0) return false; // there's definitely no-one else transmitting on the line, now we transmit - start_time = ubit.systemTime(); - now_time = start_time; - ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(1); - // wait 500ms - do { - /* - * NOTE: as with the previous loop, this is a busy wait loop - * it's particularly important that this one is accurately timed, - * as we expect ourself and the Slave to synchronise clocks on the - * falling edge of this pulse we send - */ - now_time = ubit.systemTime(); - } while ((now_time - start_time) < 500); - // bring line LO - ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(0); + this->busy_wait_drive_pin(500, start_time, now_time); // now_time is the clock synchronisation timestamp this->synchronisation_timestamp = now_time; // now, wait up to 100ms for a reply from the Slave @@ -164,7 +139,62 @@ private: return this->await_synchronisation(); } - bool pair_as_slave(); + bool 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 + // 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); + // 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 line is still HI, then it's overrun + if (pin_state == 1) return false; + // 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; + // drive line HI + this->busy_wait_drive_pin(500, start_time, end_time); + // now we just need to await synchronisation + return this->await_synchronisation(); + } + + /** + * @brief Drives the comms pin HI and performs a busy-wait loop for a given + * duration, before driving the pin LO again. + * @param duration length of time in ms to drive the pin HI for + * @param start_time[out] system timestamp (ms) that the pin went HI + * @param end_time[out] system timestamp (ms) that the pin went LO + */ + void busy_wait_drive_pin( + unsigned long duration + unsigned long& start_time, + unsigned long& end_time + ) { + start_time = ubit.systemTime(); + end_time = start_time; + ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(1); + // wait for specified duration + do { + /* + * NOTE: this is a busy wait loop with no sleep() + * this is okay as we're deliberately allowing this function to + * block the entire system, it's documented as such and we also can + * only sleep to a 6ms precision, but we want to time as accurately + * as possible + */ + end_time = ubit.systemTime(); + } while ((end_time - start_time) < duration); + // bring line LO + ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(0); + } /** * @brief Performs a busy-wait loop, continuously checking the comms pin @@ -224,6 +254,7 @@ private: do { now_time = ubit.systemTime(); } while (now_time < sync_time); + return true; // at this point, now both Master and Slave are synchronised } unsigned long synchronisation_timestamp; -- GitLab