diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2021-10-28 20:09:39 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2021-10-28 20:09:39 -0400 |
commit | 41ae9b3b1b6a75d12c39f1186e6d6e644f834c6f (patch) | |
tree | 13fc333783432c6a4117b68257cedc15552107fd | |
parent | a1700f3ca6456a3215165c7d59564c594e22cafd (diff) |
added cmake support
-rw-r--r-- | CMakeLists.txt | 31 | ||||
-rw-r--r-- | source/device.cpp | 145 | ||||
-rw-r--r-- | source/file.cpp | 5 | ||||
-rw-r--r-- | source/stmdsp/stmdsp.cpp | 5 |
4 files changed, 129 insertions, 57 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d042f12 --- /dev/null +++ b/CMakeLists.txt @@ -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) + diff --git a/source/device.cpp b/source/device.cpp index e5d7839..333fd81 100644 --- a/source/device.cpp +++ b/source/device.cpp @@ -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."); diff --git a/source/file.cpp b/source/file.cpp index f6222fa..96dac0a 100644 --- a/source/file.cpp +++ b/source/file.cpp @@ -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(); diff --git a/source/stmdsp/stmdsp.cpp b/source/stmdsp/stmdsp.cpp index 93c52dd..d219d38 100644 --- a/source/stmdsp/stmdsp.cpp +++ b/source/stmdsp/stmdsp.cpp @@ -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)); } } |