Merge branch 'windows' into devel

pull/1/head
Clyne 2 years ago
commit 93c4146982

1
.gitignore vendored

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

@ -1,26 +1,36 @@
CXX = g++
CXXFILES := \
source/serial/src/serial.cc \
source/serial/src/impl/unix.cc \
source/serial/src/impl/list_ports/list_ports_linux.cc \
$(wildcard source/imgui/backends/*.cpp) \
$(wildcard source/imgui/*.cpp) \
$(wildcard source/stmdsp/*.cpp) \
$(wildcard source/*.cpp)
OFILES := $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES)))
CXXFLAGS := -std=c++20 -O2 \
-Isource -Isource/imgui -Isource/stmdsp -Isource/serial/include \
-Wall -Wextra -pedantic #-DSTMDSP_DISABLE_FORMULAS
ifeq ($(OS),Windows_NT)
CXXFILES += source/serial/src/impl/win.cc \
source/serial/src/impl/list_ports/list_ports_win.cc
CXXFLAGS += -DSTMDSP_WIN32 -Wa,-mbig-obj
LDFLAGS = -mwindows -lSDL2 -lopengl32 -lsetupapi -lole32
OUTPUT := stmdspgui.exe
else
CXXFILES += source/serial/src/impl/unix.cc \
source/serial/src/impl/list_ports/list_ports_unix.cc
LDFLAGS = -lSDL2 -lGL -lpthread
OUTPUT := stmdspgui
endif
#CXXFLAGS := -std=c++20 -O2 \
# -Isource -Isource/imgui -Isource/stmdsp -Isource/serial/include
CXXFLAGS := -std=c++20 -ggdb -O0 -g3 \
-Isource -Isource/imgui -Isource/stmdsp -Isource/serial/include \
-Wall -Wextra -pedantic
OFILES := $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES)))
all: $(OUTPUT)
$(OUTPUT): $(OFILES)
@echo " LD " $(OUTPUT)
@g++ $(OFILES) -o $(OUTPUT) -lSDL2 -lGL -lpthread
@$(CXX) $(OFILES) -o $(OUTPUT) $(LDFLAGS)
clean:
@echo " CLEAN"
@ -28,9 +38,9 @@ clean:
%.o: %.cpp
@echo " CXX " $<
@g++ $(CXXFLAGS) -c $< -o $@
@$(CXX) $(CXXFLAGS) -c $< -o $@
%.o: %.cc
@echo " CXX " $<
@g++ $(CXXFLAGS) -c $< -o $@
@$(CXX) $(CXXFLAGS) -c $< -o $@

@ -103,8 +103,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));
@ -136,8 +138,8 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
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));
}
std::this_thread::sleep_until(next);
@ -431,15 +433,27 @@ void deviceGenLoadFormula(const std::string& formula)
std::size_t pullFromQueue(
std::deque<stmdsp::dacsample_t>& queue,
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe)
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ)
{
// 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());
@ -449,17 +463,19 @@ 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)
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ)
{
return pullFromQueue(drawSamplesQueue, circ, timeframe);
return pullFromQueue(drawSamplesQueue, circ);
}
std::size_t pullFromInputDrawQueue(
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe)
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ)
{
return pullFromQueue(drawSamplesInputQueue, circ, timeframe);
return pullFromQueue(drawSamplesInputQueue, circ);
}

@ -11,13 +11,26 @@
*/
#include "stmdsp.hpp"
#include "exprtk.hpp"
#include <algorithm>
#include <random>
#include <string_view>
#include <vector>
#ifndef STMDSP_DISABLE_FORMULAS
#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"
static std::random_device randomDevice;
std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string& formulaString)
@ -62,3 +75,12 @@ std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string& for
return samples;
}
#else // no formula support
std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&)
{
return {};
}
#endif // STMDSP_DISABLE_FORMULAS

@ -104,7 +104,7 @@ void fileRenderMenu()
if (ImGui::BeginMenu("Open Example")) {
for (const auto& file : fileExampleList) {
if (ImGui::MenuItem(file.filename().c_str())) {
if (ImGui::MenuItem(file.filename().string().c_str())) {
fileCurrentPath = file.string();
openCurrentFile();

@ -40,7 +40,7 @@ bool guiInitialize()
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
window = SDL_CreateWindow("stmdsp gui",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
550, 700,
640, 700,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE /*| SDL_WINDOW_ALLOW_HIGHDPI*/);
if (window == nullptr) {

@ -28,11 +28,9 @@ void deviceStart(bool logResults, bool drawSamples);
void deviceStartMeasurement();
void deviceUpdateDrawBufferSize(double timeframe);
std::size_t pullFromDrawQueue(
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe);
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ);
std::size_t pullFromInputDrawQueue(
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe);
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ);
static std::string sampleRatePreview = "?";
static bool measureCodeTime = false;
@ -319,19 +317,19 @@ void deviceRenderDraw()
yMinMax = std::min(4095u, (yMinMax << 1) | 1);
}
auto newSize = pullFromDrawQueue(bufferCirc, drawSamplesTimeframe);
auto newSize = pullFromDrawQueue(bufferCirc);
if (newSize > 0) {
buffer.resize(newSize);
bufferCirc = CircularBuffer(buffer);
pullFromDrawQueue(bufferCirc, drawSamplesTimeframe);
pullFromDrawQueue(bufferCirc);
}
if (drawSamplesInput) {
auto newSize = pullFromInputDrawQueue(bufferInputCirc, drawSamplesTimeframe);
auto newSize = pullFromInputDrawQueue(bufferInputCirc);
if (newSize > 0) {
bufferInput.resize(newSize);
bufferInputCirc = CircularBuffer(bufferInput);
pullFromInputDrawQueue(bufferInputCirc, drawSamplesTimeframe);
pullFromInputDrawQueue(bufferInputCirc);
}
}

@ -47,7 +47,7 @@ static ImFont *fontMono = nullptr;
template<bool first = false>
static void renderWindow();
int main(int, char **)
int main(int argc, char *argv[])
{
if (!guiInitialize())
return -1;

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