aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2021-10-28 20:09:39 -0400
committerClyne Sullivan <clyne@bitgloo.com>2021-10-28 20:09:39 -0400
commit41ae9b3b1b6a75d12c39f1186e6d6e644f834c6f (patch)
tree13fc333783432c6a4117b68257cedc15552107fd
parenta1700f3ca6456a3215165c7d59564c594e22cafd (diff)
added cmake support
-rw-r--r--CMakeLists.txt31
-rw-r--r--source/device.cpp145
-rw-r--r--source/file.cpp5
-rw-r--r--source/stmdsp/stmdsp.cpp5
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));
}
}