added cmake support

pull/1/head
Clyne 3 years ago
parent a1700f3ca6
commit 41ae9b3b1b

@ -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)

@ -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();
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();
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);
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,10 +319,10 @@ void deviceRenderWidgets()
if (logSamplesFile.good())
log("Log file ready.");
}
}
ImGuiFileDialog::Instance()->Close();
}
}
}
void deviceRenderDraw()
@ -513,7 +541,13 @@ void deviceConnect()
if (m_device == nullptr) {
stmdsp::scanner scanner;
if (auto devices = scanner.scan(); devices.size() > 0) {
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];
@ -524,6 +558,7 @@ void deviceConnect()
m_device = nullptr;
log("Failed to connect.");
}
}
} else {
log("No devices found.");
}

@ -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();

@ -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));
}
}

Loading…
Cancel
Save