diff --git a/source/ManchesterEncoder.cpp b/source/ManchesterEncoder.cpp index 411d61ce504e825910056885d30cbb9301e3c45d..1e596aca7851ffa39b9f709fc65f933c48db3a6d 100644 --- a/source/ManchesterEncoder.cpp +++ b/source/ManchesterEncoder.cpp @@ -26,36 +26,31 @@ namespace com_saxbophone { ManchesterEncoder::ManchesterEncoder() : clock(true) // our implementation has the clock signal starting HI , bit_index(0) // we definitely want to start reading bit 0 - , current_byte(0x00u) {} bool ManchesterEncoder::input(uint8_t byte) { return this->buffer.add(byte); // buffer will return false if it's full } - int ManchesterEncoder::get_next_state() { - // if we are at the start of a new byte - if (this->clock == true and this->bit_index == 0) { - // retrieve the next byte to encode and store in current_byte - if (not this->buffer.is_empty()) { - // use the buffer head and remove it from buffer - this->current_byte = this->buffer[0]; - this->buffer.shrink_from_front(1); - } else { - // use the placeholder byte 0x00 so it has something to encode - this->current_byte = 0x00u; - } - } + bool ManchesterEncoder::get_next_state(int& destination) { + // guard condition --check if buffer has content + if (this->buffer.is_empty()) return false; // Manchester Code = Clock XOR Data int symbol = this->clock xor this->extract_bit( - this->current_byte, + this->buffer[0], this->bit_index ); + destination = symbol; + // if we are at the end of a byte + if (this->clock == false and this->bit_index == 7) { + // shrink the buffer from the front by 1 to advance the buffer + this->buffer.shrink_from_front(1); + } // update bit index whenever clock is LOW (end of duration of 1 data bit) if (not this->clock) this->bit_index = (this->bit_index + 1u) % 8u; // update clock every time this->clock = not this->clock; - return symbol; + return true; } bool ManchesterEncoder::extract_bit(uint8_t byte, uint8_t bit_index) const { diff --git a/source/ManchesterEncoder.hpp b/source/ManchesterEncoder.hpp index 8c5c6cce7af3c1186ad440b8e4e1597d75b0580f..c73543d23c46e157aae2b27221376b3041dfc8c2 100644 --- a/source/ManchesterEncoder.hpp +++ b/source/ManchesterEncoder.hpp @@ -48,16 +48,14 @@ namespace com_saxbophone { bool input(uint8_t byte); /** - * @returns the next state that the encoder wants the output line to - * be set to, where 0 = LOW and 1 = HIGH - * @note the encoder never runs out of input to output --if the buffer - * becomes empty, the encoder outputs a Manchester Code sequence - * equivalent to byte 0x00 - * @warn a side effect of this method is that it advances the internal - * state of the encoder such that the next call will return the next bit - * therefore multiple calls are not idempotent. + * @brief retrieves the next state that the encoder wants the output + * line to be set to, where 0 = LOW and 1 = HIGH, stores it in + * `destination`. + * @param destination[out] the int to write the next state to + * @returns true if there was a state available and it was stored + * @returns false if no states are available yet (destination is ignored) */ - int get_next_state(); + bool get_next_state(int& destination); private: /** * @brief Extracts the bit at given index from the given byte diff --git a/source/main.cpp b/source/main.cpp index 921c858cfa7b51958f5fea6bf1c4edd445f0ac04..1562b400e5b3ff5813419ae57e618d61dd9bfba3 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -21,6 +21,8 @@ #include "MicroBit.h" +#include "ManchesterDecoder.hpp" +#include "ManchesterEncoder.hpp" #include "MorseDecoder.hpp" #include "MorseEncoder.hpp" #include "Pulse.hpp" @@ -576,7 +578,7 @@ class LineDriver { // STOP BIT ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(1); ubit.sleep(TransceiverConfig::STOP_START_BIT_DURATION_MS); - // drive low then switch to input + // drive low then switch to input mode ubit.io.pin[COMMS_PIN_NUMBER].setDigitalValue(0); ubit.io.pin[COMMS_PIN_NUMBER].getDigitalValue(); // remove transmitted bits @@ -591,7 +593,15 @@ private: // this will track the button presses ButtonTracker button_tracker; // this is used to encode bytes we want to send to go out on the line -Transceiver transceiver; +ManchesterEncoder manchester_encoder; +// this switches the line state +LineDriver line_driver; +// this is used to decode bytes from the line +ManchesterDecoder manchester_decoder; +// this monitors the line for changes +LineMonitor line_monitor(manchester_decoder); + + // flag used by the morse_checker() fiber function to check if it should run bool morse_checker_enabled = false; @@ -614,7 +624,7 @@ void morse_checker() { * NOTE: for now, just sending characters as-is but in the future * they will be encoded rather than sent raw */ - transceiver.send(current); // NOTE: Might need cast + manchester_encoder.input(current); // NOTE: Might need cast } else { // otherwise, peek into what the code appears to be thus far char peek = morse_decoder.peek(); @@ -628,6 +638,27 @@ 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 + int next_state = 0; + while (manchester_encoder.get_next_state(next_state)) { + line_driver.input(next_state); + } + } +} + + +// 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 + line_monitor.flush(); + } +} + + int main() { // Initialise the micro:bit runtime. ubit.init(); @@ -636,7 +667,10 @@ int main() { ubit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE); // create one fiber --this infinitely checks the decoder and outputs changes - // create_fiber(morse_checker); + 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) { @@ -672,11 +706,14 @@ int main() { while (true) { // TODO: consider what exit conditions can be used // call barrier to synchronise both master and slave pairer.barrier(); + // flush the line driver + line_driver.flush(); } } else { // Slave's comms loop while (true) { // TODO: consider what exit conditions can be used // call barrier to synchronise both master and slave pairer.barrier(); + // TODO: display the output? } } diff --git a/tests/manchester_encoder_decoder_test.cpp b/tests/manchester_encoder_decoder_test.cpp index 1a12dff37f4e7d281589e4817aa3a9494d128ef3..c6d6ca03d00a11a583bc5df82c0e9699bd250ce8 100644 --- a/tests/manchester_encoder_decoder_test.cpp +++ b/tests/manchester_encoder_decoder_test.cpp @@ -39,7 +39,8 @@ int main() { printf("\n"); printf("Actual: \t"); for (size_t i = 0; i < 16; i++) { - int state = encoder.get_next_state(); + int state = 0; + encoder.get_next_state(state); assert(state == t.output[i]); decoder.input(state); printf("%u", state); @@ -63,7 +64,8 @@ int main() { printf("%02x -> ", b); encoder.input(b); for (uint8_t i = 0; i < 16; i++) { - int symbol = encoder.get_next_state(); + int symbol; + encoder.get_next_state(symbol); printf("%d", symbol); decoder.input(symbol); }