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); + } } }