]> code.bitgloo.com Git - clyne/stmdspgui.git/commitdiff
bug fixes; dynamic time measure; sync sample drawing
authorClyne Sullivan <clyne@bitgloo.com>
Sun, 22 May 2022 17:29:45 +0000 (13:29 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Sun, 22 May 2022 17:29:45 +0000 (13:29 -0400)
source/circular.hpp
source/code.cpp
source/device.cpp
source/gui_device.cpp
source/stmdsp/stmdsp.cpp
source/stmdsp/stmdsp.hpp

index 6b820683454690878b80479f144ca52c26068b43..4f49322e28ffd136c380d76faff1b1861b00430b 100644 (file)
@@ -21,7 +21,7 @@ public:
     CircularBuffer(Container<T>& container) :
         m_begin(std::begin(container)),
         m_end(std::end(container)),
-        m_current(std::begin(container)) {}
+        m_current(m_begin) {}
 
     void put(const T& value) noexcept {
         *m_current = value;
@@ -33,6 +33,11 @@ public:
         return std::distance(m_begin, m_end);
     }
 
+    void reset(const T& fill) noexcept {
+        std::fill(m_begin, m_end, fill);
+        m_current = m_begin;
+    }
+
 private:
     Container<T>::iterator m_begin;
     Container<T>::iterator m_end;
index 14f603c4b92fb9f8cb3311c2b72d2828b111c53c..8e3bd6c578374450693473a6a992df7ec5806e8e 100644 (file)
@@ -134,18 +134,17 @@ std::string newTempFileName()
 bool codeExecuteCommand(const std::string& command, const std::string& file)
 {
     bool success = system(command.c_str()) == 0;
-    if (success) {
-        if (std::ifstream output (file); output.good()) {
-            std::ostringstream sstr;
-            sstr << output.rdbuf();
-            log(sstr.str().c_str());
-        } else {
-            log("Could not read command output!");
-        }
-
-        std::filesystem::remove(file);
+
+    if (std::ifstream output (file); output.good()) {
+        std::ostringstream sstr;
+        sstr << output.rdbuf();
+        log(sstr.str().c_str());
+    } else {
+        log("Could not read command output!");
     }
 
+    std::filesystem::remove(file);
+
     return success;
 }
 
index 11e181e8a3671b43597788337713685731938034..60b1bc9a0cc79099986651e3b0b4ba7b1c8dc756 100644 (file)
@@ -33,6 +33,7 @@
 extern void log(const std::string& str);
 extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&);
 extern std::ifstream compileOpenBinaryFile();
+extern void deviceRenderDisconnect();
 
 std::shared_ptr<stmdsp::device> m_device;
 
@@ -45,9 +46,15 @@ static std::deque<stmdsp::dacsample_t> drawSamplesInputQueue;
 static bool drawSamplesInput = false;
 static unsigned int drawSamplesBufferSize = 1;
 
+bool deviceConnect();
+
 void deviceSetInputDrawing(bool enabled)
 {
     drawSamplesInput = enabled;
+    if (enabled) {
+        drawSamplesQueue.clear();
+        drawSamplesInputQueue.clear();
+    }
 }
 
 static void measureCodeTask(std::shared_ptr<stmdsp::device> device)
@@ -55,7 +62,7 @@ static void measureCodeTask(std::shared_ptr<stmdsp::device> device)
     std::this_thread::sleep_for(std::chrono::seconds(1));
 
     if (device) {
-        const auto cycles = device->continuous_start_get_measurement();
+        const auto cycles = device->measurement_read();
         log(std::string("Execution time: ") + std::to_string(cycles) + " cycles.");
     }
 }
@@ -109,11 +116,21 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
         const auto next = std::chrono::high_resolution_clock::now() + bufferTime;
 
         if (lockDevice.try_lock_until(next)) {
-            const auto chunk = tryReceiveChunk(device,
+            std::vector<stmdsp::dacsample_t> chunk, chunk2;
+
+            chunk = tryReceiveChunk(device,
                 std::mem_fn(&stmdsp::device::continuous_read));
+            if (drawSamplesInput) {
+                chunk2 = tryReceiveChunk(device,
+                    std::mem_fn(&stmdsp::device::continuous_read_input));
+            }
+
             lockDevice.unlock();
 
             addToQueue(drawSamplesQueue, chunk);
+            if (drawSamplesInput)
+                addToQueue(drawSamplesInputQueue, chunk2);
+
             if (logSamplesFile.is_open()) {
                 for (const auto& s : chunk)
                     logSamplesFile << s << '\n';
@@ -123,16 +140,6 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
             std::this_thread::sleep_for(std::chrono::milliseconds(500));
         }
 
-        if (drawSamplesInput) {
-            if (lockDevice.try_lock_for(std::chrono::milliseconds(1))) {
-                const auto chunk2 = tryReceiveChunk(device,
-                    std::mem_fn(&stmdsp::device::continuous_read_input));
-                lockDevice.unlock();
-
-                addToQueue(drawSamplesInputQueue, chunk2);
-            }
-        }
-
         std::this_thread::sleep_until(next);
     }
 }
@@ -193,6 +200,12 @@ static void statusTask(std::shared_ptr<stmdsp::device> device)
             case stmdsp::Error::ConversionAborted:
                 log("Error: Algorithm unloaded, a fault occurred!");
                 break;
+            case stmdsp::Error::GUIDisconnect:
+                // Do GUI events for disconnect if device was lost.
+                deviceConnect();
+                deviceRenderDisconnect();
+                return;
+                break;
             default:
                 log("Error: Device had an issue...");
                 break;
@@ -301,7 +314,7 @@ bool deviceConnect()
     return false;
 }
 
-void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples)
+void deviceStart(bool logResults, bool drawSamples)
 {
     if (!m_device) {
         log("No device connected.");
@@ -320,18 +333,22 @@ void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples)
         }
         log("Ready.");
     } else {
-        if (measureCodeTime) {
-            m_device->continuous_start_measure();
-            std::thread(measureCodeTask, m_device).detach();
-        } else {
-            m_device->continuous_start();
-            if (drawSamples || logResults || wavOutput.valid())
-                std::thread(drawSamplesTask, m_device).detach();
-        }
+        m_device->continuous_start();
+        if (drawSamples || logResults || wavOutput.valid())
+            std::thread(drawSamplesTask, m_device).detach();
+
         log("Running.");
     }
 }
 
+void deviceStartMeasurement()
+{
+    if (m_device && m_device->is_running()) {
+        m_device->measurement_start();
+        std::thread(measureCodeTask, m_device).detach();
+    }
+}
+
 void deviceAlgorithmUpload()
 {
     if (!m_device) {
@@ -387,7 +404,7 @@ void deviceGenLoadList(const std::string_view list)
             }
         }
 
-        it = itend;
+        it = std::find_if(itend, list.cend(), isdigit);
     }
 
     if (it == list.cend()) {
index 43c0a581bae35a1c4c8c0dea35ad03c209db3074..f846414d1766991677b77d8762de966e76712f72 100644 (file)
@@ -24,7 +24,8 @@ void deviceLoadAudioFile(const std::string& file);
 void deviceLoadLogFile(const std::string& file);
 void deviceSetSampleRate(unsigned int index);
 void deviceSetInputDrawing(bool enabled);
-void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples);
+void deviceStart(bool logResults, bool drawSamples);
+void deviceStartMeasurement();
 void deviceUpdateDrawBufferSize(double timeframe);
 std::size_t pullFromDrawQueue(
     CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
@@ -47,6 +48,15 @@ static std::string getSampleRatePreview(unsigned int rate)
     return std::to_string(rate / 1000) + " kHz";
 }
 
+static std::string connectLabel ("Connect");
+void deviceRenderDisconnect()
+{
+    connectLabel = "Connect";
+    measureCodeTime = false;
+    logResults = false;
+    drawSamples = false;
+}
+
 void deviceRenderMenu()
 {
     auto addMenuItem = [](const std::string& label, bool enable, auto action) {
@@ -56,7 +66,6 @@ void deviceRenderMenu()
     };
 
     if (ImGui::BeginMenu("Device")) {
-        static std::string connectLabel ("Connect");
         addMenuItem(connectLabel, !m_device || !m_device->is_running(), [&] {
                 if (deviceConnect()) {
                     connectLabel = "Disconnect";
@@ -64,10 +73,7 @@ void deviceRenderMenu()
                         getSampleRatePreview(m_device->get_sample_rate());
                     deviceUpdateDrawBufferSize(drawSamplesTimeframe);
                 } else {
-                    connectLabel = "Connect";
-                    measureCodeTime = false;
-                    logResults = false;
-                    drawSamples = false;
+                    deviceRenderDisconnect();
                 }
             });
 
@@ -79,7 +85,7 @@ void deviceRenderMenu()
         static std::string startLabel ("Start");
         addMenuItem(startLabel, isConnected, [&] {
                 startLabel = isRunning ? "Start" : "Stop";
-                deviceStart(measureCodeTime, logResults, drawSamples);
+                deviceStart(logResults, drawSamples);
                 if (logResults && isRunning)
                     logResults = false;
             });
@@ -87,28 +93,25 @@ void deviceRenderMenu()
             deviceAlgorithmUpload);
         addMenuItem("Unload algorithm", isConnected && !isRunning,
             deviceAlgorithmUnload);
+        addMenuItem("Measure Code Time", isRunning, deviceStartMeasurement);
 
         ImGui::Separator();
         if (!isConnected || isRunning)
-            ImGui::PushDisabled();
+            ImGui::PushDisabled(); // Hey, pushing disabled!
 
-        ImGui::Checkbox("Measure Code Time", &measureCodeTime);
         ImGui::Checkbox("Draw samples", &drawSamples);
         if (ImGui::Checkbox("Log results...", &logResults)) {
             if (logResults)
                 popupRequestLog = true;
         }
+        addMenuItem("Set buffer size...", true, [] { popupRequestBuffer = true; });
 
         if (!isConnected || isRunning)
             ImGui::PopDisabled();
-
-        addMenuItem("Set buffer size...", isConnected && !isRunning,
-            [] { popupRequestBuffer = true; });
-
         ImGui::Separator();
 
         addMenuItem("Load signal generator",
-            isConnected && !m_device->is_siggening(),
+            isConnected && !m_device->is_siggening() && !m_device->is_running(),
             [] { popupRequestSiggen = true; });
 
         static std::string startSiggenLabel ("Start signal generator");
@@ -193,7 +196,7 @@ void deviceRenderWidgets()
             }
         } else {
             ImGui::Text(siggenOption == 0 ? "Enter a list of numbers:"
-                                          : "Enter a formula. f(x) = ");
+                                          : "Enter a formula. x = sample #, y = -1 to 1.\nf(x) = ");
             ImGui::PushStyleColor(ImGuiCol_FrameBg, {.8, .8, .8, 1});
             ImGui::InputText("", siggenInput.data(), siggenInput.size());
             ImGui::PopStyleColor();
@@ -286,8 +289,13 @@ void deviceRenderDraw()
         ImGui::Begin("draw", &drawSamples);
         ImGui::Text("Draw input ");
         ImGui::SameLine();
-        if (ImGui::Checkbox("", &drawSamplesInput))
+        if (ImGui::Checkbox("", &drawSamplesInput)) {
             deviceSetInputDrawing(drawSamplesInput);
+            if (drawSamplesInput) {
+                bufferCirc.reset(2048);
+                bufferInputCirc.reset(2048);
+            }
+        }
         ImGui::SameLine();
         ImGui::Text("Time: %0.3f sec", drawSamplesTimeframe);
         ImGui::SameLine();
index 22523647aacc8736ba7a0fd740423d00b5ab3a8a..d7e977bff987ad8204ad9734b7b771a752b19856 100644 (file)
@@ -90,8 +90,7 @@ namespace stmdsp
                 m_serial->write(cmd.data(), cmd.size());
                 success = true;
             } catch (...) {
-                m_serial.release();
-                log("Lost connection!");
+                handle_disconnect();
             }
         }
 
@@ -108,8 +107,7 @@ namespace stmdsp
                 m_serial->read(dest, dest_size);
                 success = true;
             } catch (...) {
-                m_serial.release();
-                log("Lost connection!");
+                handle_disconnect();
             }
         }
 
@@ -158,12 +156,11 @@ namespace stmdsp
             m_is_running = true;
     }
 
-    void device::continuous_start_measure() {
-        if (try_command({'M'}))
-            m_is_running = true;
+    void device::measurement_start() {
+        try_command({'M'});
     }
 
-    uint32_t device::continuous_start_get_measurement() {
+    uint32_t device::measurement_read() {
         uint32_t count = 0;
         try_read({'m'}, reinterpret_cast<uint8_t *>(&count), sizeof(uint32_t));
         return count / 2;
@@ -193,8 +190,7 @@ namespace stmdsp
 
                 }
             } catch (...) {
-                m_serial.release();
-                log("Lost connection!");
+                handle_disconnect();
             }
         }
 
@@ -225,8 +221,7 @@ namespace stmdsp
 
                 }
             } catch (...) {
-                m_serial.release();
-                log("Lost connection!");
+                handle_disconnect();
             }
         }
 
@@ -251,8 +246,7 @@ namespace stmdsp
                     m_serial->write(request, 3);
                     m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t));
                 } catch (...) {
-                    m_serial.release();
-                    log("Lost connection!");
+                    handle_disconnect();
                 }
             } else {
                 try {
@@ -262,8 +256,7 @@ namespace stmdsp
                     else
                         m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t));
                 } catch (...) {
-                    m_serial.release();
-                    log("Lost connection!");
+                    handle_disconnect();
                 }
             }
 
@@ -295,8 +288,7 @@ namespace stmdsp
                 m_serial->write(request, 3);
                 m_serial->write(buffer, size);
             } catch (...) {
-                m_serial.release();
-                log("Lost connection!");
+                handle_disconnect();
             }
         }
     }
@@ -318,9 +310,19 @@ namespace stmdsp
             bool running = ret.first == RunStatus::Running;
             if (m_is_running != running)
                 m_is_running = running;
+        } else if (m_disconnect_error_flag) {
+            m_disconnect_error_flag = false;
+            return {RunStatus::Idle, Error::GUIDisconnect};
         }
 
         return ret;
     }
-}
+
+    void device::handle_disconnect()
+    {
+        m_disconnect_error_flag = true;
+        m_serial.release();
+        log("Lost connection!");
+    }
+} // namespace stmdsp
 
index e0fca90d818e563f32b6d12fe849b95a3c794215..efed8a36905d615bbb9c90882458981dc9dee3d1 100644 (file)
@@ -63,12 +63,15 @@ namespace stmdsp
      */
     enum class Error : char {
         None = 0,
-        BadParam,         /* An invalid parameter was passed for a command. */
-        BadParamSize,     /* An invaild param. size was given for a command. */
-        BadUserCodeLoad,  /* Device failed to load the given algorithm. */
-        BadUserCodeSize,  /* The given algorithm is too large for the device. */
-        NotIdle,          /* An idle-only command was received while not Idle. */
-        ConversionAborted /* A conversion was aborted due to a fault. */
+        BadParam,            /* An invalid parameter was passed for a command. */
+        BadParamSize,        /* An invaild param. size was given for a command. */
+        BadUserCodeLoad,     /* Device failed to load the given algorithm. */
+        BadUserCodeSize,     /* The given algorithm is too large for the device. */
+        NotIdle,             /* An idle-only command was received while not Idle. */
+        ConversionAborted,   /* A conversion was aborted due to a fault. */
+        NotRunning,          /* A running-only command was received while not Running. */
+
+        GUIDisconnect = 100  /* The GUI lost connection with the device. */
     };
 
     /**
@@ -123,8 +126,8 @@ namespace stmdsp
         void continuous_start();
         void continuous_stop();
 
-        void continuous_start_measure();
-        uint32_t continuous_start_get_measurement();
+        void measurement_start();
+        uint32_t measurement_read();
 
         std::vector<adcsample_t> continuous_read();
         std::vector<adcsample_t> continuous_read_input();
@@ -149,11 +152,13 @@ namespace stmdsp
         unsigned int m_sample_rate = 0;
         bool m_is_siggening = false;
         bool m_is_running = false;
+        bool m_disconnect_error_flag = false;
 
         std::mutex m_lock;
 
         bool try_command(std::basic_string<uint8_t> data);
         bool try_read(std::basic_string<uint8_t> cmd, uint8_t *dest, unsigned int dest_size);
+        void handle_disconnect();
     };
 }