diff --git a/.gitignore b/.gitignore index d7ed0eb..9c562a6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ stmdspgui stmdspgui.exe perf.data* *.o +*.dll .* diff --git a/Makefile b/Makefile index fdf87d6..1f4b1e1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ #linux: CXXFILES += source/serial/src/impl/unix.cc source/serial/src/impl/list_ports/list_ports_unix.cc #linux: LDFLAGS = -lSDL2 -lGL -lpthread -CROSS = x86_64-w64-mingw32- -CXX = $(CROSS)g++ +#CROSS = x86_64-w64-mingw32- +#CXX = $(CROSS)g++ +CXX = g++ CXXFILES := \ source/serial/src/serial.cc \ diff --git a/source/device.cpp b/source/device.cpp index 11e181e..edd950c 100644 --- a/source/device.cpp +++ b/source/device.cpp @@ -96,8 +96,10 @@ static void drawSamplesTask(std::shared_ptr device) if (!device) return; - const auto bufferTime = getBufferPeriod(device); + // This is the amount of time to wait between device reads. + const auto bufferTime = getBufferPeriod(device, 1); + // Adds the given chunk of samples to the given queue. const auto addToQueue = [](auto& queue, const auto& chunk) { std::scoped_lock lock (mutexDrawSamples); std::copy(chunk.cbegin(), chunk.cend(), std::back_inserter(queue)); @@ -114,13 +116,14 @@ static void drawSamplesTask(std::shared_ptr device) lockDevice.unlock(); addToQueue(drawSamplesQueue, chunk); + if (logSamplesFile.is_open()) { for (const auto& s : chunk) logSamplesFile << s << '\n'; } } else { - // Device must be busy, cooldown. - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // Device must be busy, back off for a bit. + std::this_thread::sleep_for(std::chrono::milliseconds(50)); } if (drawSamplesInput) { @@ -417,12 +420,25 @@ std::size_t pullFromQueue( CircularBuffer& circ, double timeframe) { + // We know how big the circular buffer should be to hold enough samples to + // fill the current draw samples view. + // If the given buffer does not match this size, notify the caller. + // TODO this could be done better... drawSamplesBufferSize should be a GUI- + // only thing. if (circ.size() != drawSamplesBufferSize) return drawSamplesBufferSize; std::scoped_lock lock (mutexDrawSamples); - const auto desiredCount = drawSamplesBufferSize / (60. * timeframe) * 1.025; + // The render code will draw all of the new samples we add to the buffer. + // So, we must provide a certain amount of samples at a time to make the + // render appear smooth. + // The 1.025 factor keeps us on top of the stream; don't want to fall + // behind. + const double FPS = ImGui::GetIO().Framerate; + const auto desiredCount = m_device->get_sample_rate() / FPS; + + // Transfer from the queue to the render buffer. auto count = std::min(queue.size(), static_cast(desiredCount)); while (count--) { circ.put(queue.front()); @@ -432,6 +448,10 @@ std::size_t pullFromQueue( return 0; } +/** + * Pulls a render frame's worth of samples from the draw samples queue, adding + * the samples to the given buffer. + */ std::size_t pullFromDrawQueue( CircularBuffer& circ, double timeframe) diff --git a/source/device_formula.cpp b/source/device_formula.cpp index a70f465..9a3372f 100644 --- a/source/device_formula.cpp +++ b/source/device_formula.cpp @@ -10,9 +10,20 @@ * If not, see . */ -#include "stmdsp.hpp" +#define exprtk_disable_comments +#define exprtk_disable_break_continue +#define exprtk_disable_sc_andor +#define exprtk_disable_return_statement +#define exprtk_disable_enhanced_features +//#define exprtk_disable_string_capabilities +#define exprtk_disable_superscalar_unroll +#define exprtk_disable_rtl_io_file +#define exprtk_disable_rtl_vecops +//#define exprtk_disable_caseinsensitivity #include "exprtk.hpp" +#include "stmdsp.hpp" + #include #include #include diff --git a/source/stmdsp/stmdsp.cpp b/source/stmdsp/stmdsp.cpp index 2252364..c835257 100644 --- a/source/stmdsp/stmdsp.cpp +++ b/source/stmdsp/stmdsp.cpp @@ -45,7 +45,9 @@ namespace stmdsp device::device(const std::string& file) { // This could throw! - m_serial.reset(new serial::Serial(file, 8'000'000, serial::Timeout::simpleTimeout(50))); + // Note: Windows needs a not-simple, positive timeout like this to + // ensure that reads block. + m_serial.reset(new serial::Serial(file, 921'600 /*8'000'000*/, serial::Timeout(1000, 1000, 1, 1000, 1))); // Test the ID command. m_serial->flush();