From c595bd2a151f69710bb1a4a61c839c3ea16bbfc0 Mon Sep 17 00:00:00 2001
From: Joshua Saxby <joshua.a.saxby@gmail.com>
Date: Sun, 8 Mar 2020 20:48:49 +0000
Subject: [PATCH] Rewrote some stuff and modified, pulling together
 transmission code

---
 source/ManchesterEncoder.cpp              | 27 ++++++--------
 source/ManchesterEncoder.hpp              | 16 ++++----
 source/main.cpp                           | 45 +++++++++++++++++++++--
 tests/manchester_encoder_decoder_test.cpp |  6 ++-
 4 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/source/ManchesterEncoder.cpp b/source/ManchesterEncoder.cpp
index 411d61c..1e596ac 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 8c5c6cc..c73543d 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 921c858..1562b40 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 1a12dff..c6d6ca0 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);
         }
-- 
GitLab