aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2022-05-17 11:42:14 -0800
committerClyne Sullivan <clyne@bitgloo.com>2022-05-17 11:42:14 -0800
commit29636cfebf58094d61b669d99c08a4f76dc98a8c (patch)
treea8d8c4399ab01e78284db38797175167b46a6afc
parent67ffe1f2ce9f3432cb524dced5e6fba96519b4fd (diff)
fix serial timeout to prevent incomplete IO
-rw-r--r--.gitignore1
-rw-r--r--Makefile5
-rw-r--r--source/device.cpp28
-rw-r--r--source/device_formula.cpp13
-rw-r--r--source/stmdsp/stmdsp.cpp4
5 files changed, 43 insertions, 8 deletions
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<stmdsp::device> 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<stmdsp::device> 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<std::vector, stmdsp::dacsample_t>& 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<std::size_t>(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<std::vector, stmdsp::dacsample_t>& 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 <https://www.gnu.org/licenses/>.
*/
-#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 <algorithm>
#include <random>
#include <string_view>
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();