fix serial timeout to prevent incomplete IO

pull/1/head
Clyne 3 years ago
parent 67ffe1f2ce
commit 29636cfebf

1
.gitignore vendored

@ -4,4 +4,5 @@ stmdspgui
stmdspgui.exe
perf.data*
*.o
*.dll
.*

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

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

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

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

Loading…
Cancel
Save