]> code.bitgloo.com Git - clyne/stmdspgui.git/commitdiff
added cmake support
authorClyne Sullivan <clyne@bitgloo.com>
Fri, 29 Oct 2021 00:09:39 +0000 (20:09 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Fri, 29 Oct 2021 00:09:39 +0000 (20:09 -0400)
CMakeLists.txt [new file with mode: 0644]
source/device.cpp
source/file.cpp
source/stmdsp/stmdsp.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d042f12
--- /dev/null
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(stmdspgui VERSION 0.5)
+
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+add_compile_options(-O0 -ggdb -g3 -Wall -Wextra -pedantic)
+
+file(GLOB SRC_IMGUI_BACKENDS "${CMAKE_SOURCE_DIR}/source/imgui/backends/*.cpp")
+file(GLOB SRC_IMGUI "${CMAKE_SOURCE_DIR}/source/imgui/*.cpp")
+file(GLOB SRC_STMDSP "${CMAKE_SOURCE_DIR}/source/stmdsp/*.cpp")
+file(GLOB SRC_STMDSPGUI "${CMAKE_SOURCE_DIR}/source/*.cpp")
+
+add_executable(stmdspgui
+    source/serial/src/serial.cc
+    source/serial/src/impl/unix.cc
+    source/serial/src/impl/list_ports/list_ports_linux.cc
+    ${SRC_IMGUI_BACKENDS}
+    ${SRC_IMGUI}
+    ${SRC_STMDSP}
+    ${SRC_STMDSPGUI})
+
+target_include_directories(stmdspgui PUBLIC
+    ${CMAKE_SOURCE_DIR}/source
+    ${CMAKE_SOURCE_DIR}/source/imgui
+    ${CMAKE_SOURCE_DIR}/source/stmdsp
+    ${CMAKE_SOURCE_DIR}/source/serial/include)
+
+target_link_libraries(stmdspgui PRIVATE SDL2 GL pthread)
+
index e5d7839dfb250c9dfb88391ef538cd3f0b20e956..333fd819eccf59661b759984f3b0722334d8babc 100644 (file)
@@ -11,9 +11,7 @@
 
 /**
  * TODO list:
- * - Test loading the signal generator with a formula.
  * - Improve signal generator audio streaming.
- * - Log samples (should be good..?)
  */
 
 #include "stmdsp.hpp"
@@ -25,9 +23,9 @@
 #include <array>
 #include <charconv>
 #include <cmath>
-#include <cstdio>
 #include <deque>
 #include <fstream>
+#include <iostream>
 #include <mutex>
 #include <thread>
 
@@ -66,9 +64,9 @@ static bool popupRequestSiggen = false;
 static bool popupRequestDraw = false;
 static bool popupRequestLog = false;
 
-static std::mutex mutexDrawSamples;
-//static std::vector<stmdsp::dacsample_t> drawSamplesBuf;
-static std::vector<stmdsp::dacsample_t> drawSamplesBuf2;
+static std::timed_mutex mutexDrawSamples;
+static std::timed_mutex mutexDeviceLoad;
+
 static std::ofstream logSamplesFile;
 static wav::clip wavOutput;
 
@@ -97,41 +95,64 @@ static void drawSamplesTask(stmdsp::device *device)
     const double sampleRate = sampleRateInts[m_device->get_sample_rate()];
     unsigned long bufferTime = bufferSize / sampleRate * 0.975 * 1e6;
 
+    std::unique_lock<std::timed_mutex> lockDraw (mutexDrawSamples, std::defer_lock);
+    std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
+
     while (m_device && m_device->is_running()) {
         auto next = std::chrono::high_resolution_clock::now() +
                     std::chrono::microseconds(bufferTime);
 
-        auto chunk = m_device->continuous_read();
-        while (chunk.empty() && m_device->is_running()) {
-            std::this_thread::sleep_for(std::chrono::microseconds(20));
+        std::vector<stmdsp::dacsample_t> chunk;
+
+       if (lockDevice.try_lock_until(next)) {
             chunk = m_device->continuous_read();
-        }
+            int tries = -1;
+            while (chunk.empty() && m_device->is_running()) {
+                if (++tries == 100)
+                    break;
+                std::this_thread::sleep_for(std::chrono::microseconds(20));
+                chunk = m_device->continuous_read();
+            }
+           lockDevice.unlock();
+       } else {
+            // Cooldown.
+            std::this_thread::sleep_for(std::chrono::milliseconds(500));
+       }
 
         if (drawSamplesInput && popupRequestDraw) {
-            auto chunk2 = m_device->continuous_read_input();
-            while (chunk2.empty() && m_device->is_running()) {
-                std::this_thread::sleep_for(std::chrono::microseconds(20));
+            std::vector<stmdsp::dacsample_t> chunk2;
+
+           if (lockDevice.try_lock_for(std::chrono::milliseconds(1))) {
                 chunk2 = m_device->continuous_read_input();
+                int tries = -1;
+                while (chunk2.empty() && m_device->is_running()) {
+                    if (++tries == 100)
+                        break;
+                    std::this_thread::sleep_for(std::chrono::microseconds(20));
+                    chunk2 = m_device->continuous_read_input();
+                }
+               lockDevice.unlock();
             }
 
-            {
-                std::scoped_lock lock (mutexDrawSamples);
-                auto i = chunk2.cbegin();
-                for (const auto& s : chunk) {
-                    drawSamplesQueue.push_back(s);
-                    drawSamplesInputQueue.push_back(*i++);
-                }
+           lockDraw.lock();
+            auto i = chunk2.cbegin();
+            for (const auto& s : chunk) {
+                drawSamplesQueue.push_back(s);
+                drawSamplesInputQueue.push_back(*i++);
             }
+           lockDraw.unlock();
         } else if (!doLogger) {
-            std::scoped_lock lock (mutexDrawSamples);
+           lockDraw.lock();
             for (const auto& s : chunk)
                 drawSamplesQueue.push_back(s);
+           lockDraw.unlock();
         } else {
-            std::scoped_lock lock (mutexDrawSamples);
+           lockDraw.lock();
             for (const auto& s : chunk) {
                 drawSamplesQueue.push_back(s);
                 logSamplesFile << s << '\n';
             }
+           lockDraw.unlock();
         }
         
         std::this_thread::sleep_until(next);
@@ -143,33 +164,37 @@ static void feedSigGenTask(stmdsp::device *device)
     if (device == nullptr)
         return;
 
-    const auto bsize = m_device->get_buffer_size();
-    const float srate = sampleRateInts[m_device->get_sample_rate()];
-    const unsigned int delay = bsize / srate * 1000.f * 0.4f;
+    const auto bufferSize = m_device->get_buffer_size();
+    const double sampleRate = sampleRateInts[m_device->get_sample_rate()];
+    const unsigned long delay = bufferSize / sampleRate * 0.975 * 1e6;
+
+    std::vector<stmdsp::adcsample_t> wavBuf (bufferSize, 2048);
 
-    auto wavBuf = new stmdsp::adcsample_t[bsize];
+    std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
 
-    {
-        auto dst = wavBuf;
-        auto src = reinterpret_cast<uint16_t *>(wavOutput.next(bsize));
-        for (auto i = 0u; i < bsize; ++i)
-            *dst++ = *src++ / 16 + 2048;
-        m_device->siggen_upload(wavBuf, bsize);
-    }
+    lockDevice.lock();
+    // One (or both) of these freezes the device...
+    m_device->siggen_upload(wavBuf.data(), wavBuf.size());
+    //m_device->siggen_start();
+    lockDevice.unlock();
 
-    m_device->siggen_start();
+    std::this_thread::sleep_for(std::chrono::microseconds(delay));
 
+    return;
     while (genRunning) {
-        auto dst = wavBuf;
-        auto src = reinterpret_cast<uint16_t *>(wavOutput.next(bsize));
-        for (auto i = 0u; i < bsize; ++i)
-            *dst++ = *src++ / 16 + 2048;
-        m_device->siggen_upload(wavBuf, bsize);
+        auto next = std::chrono::high_resolution_clock::now() +
+                    std::chrono::microseconds(delay);
 
-        std::this_thread::sleep_for(std::chrono::milliseconds(delay));
-    }
+        auto src = reinterpret_cast<uint16_t *>(wavOutput.next(bufferSize));
+        for (auto& w : wavBuf)
+            w = *src++ / 16 + 2048;
 
-    delete[] wavBuf;
+        if (lockDevice.try_lock_until(next)) {
+            m_device->siggen_upload(wavBuf.data(), wavBuf.size());
+           lockDevice.unlock();
+            std::this_thread::sleep_until(next);
+        }
+    }
 }
 
 static void deviceConnect();
@@ -273,7 +298,10 @@ void deviceRenderWidgets()
         ImGui::EndPopup();
     }
 
-    if (ImGuiFileDialog::Instance()->Display("ChooseFileLogGen")) {
+    if (ImGuiFileDialog::Instance()->Display("ChooseFileLogGen",
+                                             ImGuiWindowFlags_NoCollapse,
+                                             ImVec2(460, 540)))
+    {
         if (ImGuiFileDialog::Instance()->IsOk()) {
             auto filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
             auto ext = filePathName.substr(filePathName.size() - 4);
@@ -291,9 +319,9 @@ void deviceRenderWidgets()
                 if (logSamplesFile.good())
                     log("Log file ready.");
             }
-
-            ImGuiFileDialog::Instance()->Close();
         }
+
+        ImGuiFileDialog::Instance()->Close();
     }
 }
 
@@ -513,16 +541,23 @@ void deviceConnect()
     if (m_device == nullptr) {
         stmdsp::scanner scanner;
         if (auto devices = scanner.scan(); devices.size() > 0) {
-            m_device = new stmdsp::device(devices.front());
-            if (m_device->connected()) {
-                auto sri = m_device->get_sample_rate();
-                sampleRatePreview = sampleRateList[sri];
-                drawSamplesBufferSize = std::round(sampleRateInts[sri] * drawSamplesTimeframe);
-                log("Connected!");
-            } else {
-                delete m_device;
-                m_device = nullptr;
-                log("Failed to connect.");
+            try {
+                m_device = new stmdsp::device(devices.front());
+            } catch (...) {
+                log("Failed to connect (check permissions?).");
+               m_device = nullptr;
+            }
+            if (m_device != nullptr) {
+                if (m_device->connected()) {
+                    auto sri = m_device->get_sample_rate();
+                    sampleRatePreview = sampleRateList[sri];
+                    drawSamplesBufferSize = std::round(sampleRateInts[sri] * drawSamplesTimeframe);
+                    log("Connected!");
+                } else {
+                    delete m_device;
+                    m_device = nullptr;
+                    log("Failed to connect.");
+                }
             }
         } else {
             log("No devices found.");
index f6222fae5e14bb0b99291ec59e64467493e201d4..96dac0a7447510afabeda8edb75fa040f457ce28 100644 (file)
@@ -122,7 +122,10 @@ void fileRenderMenu()
 
 void fileRenderDialog()
 {
-    if (ImGuiFileDialog::Instance()->Display("ChooseFileOpenSave")) {
+    if (ImGuiFileDialog::Instance()->Display("ChooseFileOpenSave",
+                                             ImGuiWindowFlags_NoCollapse,
+                                             ImVec2(460, 540)))
+    {
         if (ImGuiFileDialog::Instance()->IsOk()) {
             std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
 
index 93c52dd22ba986ba6bbcbf1eb020e8666e536ad1..d219d38fd03b265cd3a873c699d8fb36a1a32f56 100644 (file)
@@ -27,7 +27,7 @@ namespace stmdsp
     }
 
     device::device(const std::string& file) :
-        m_serial(file, 8'000'000/*230400*/, serial::Timeout::simpleTimeout(50))
+        m_serial(file, 8'000'000, serial::Timeout::simpleTimeout(50))
     {
         if (m_serial.isOpen()) {
             m_serial.flush();
@@ -178,6 +178,9 @@ namespace stmdsp
             m_serial.write(request, 3);
 
             m_serial.write((uint8_t *)buffer, size * sizeof(dacsample_t));
+           // TODO
+           if (!m_is_running)
+               m_serial.write((uint8_t *)buffer, size * sizeof(dacsample_t));
         }
     }