diff --git a/source/circular.hpp b/source/circular.hpp index 6b82068..4f49322 100644 --- a/source/circular.hpp +++ b/source/circular.hpp @@ -21,7 +21,7 @@ public: CircularBuffer(Container& container) : m_begin(std::begin(container)), m_end(std::end(container)), - m_current(std::begin(container)) {} + m_current(m_begin) {} void put(const T& value) noexcept { *m_current = value; @@ -33,6 +33,11 @@ public: return std::distance(m_begin, m_end); } + void reset(const T& fill) noexcept { + std::fill(m_begin, m_end, fill); + m_current = m_begin; + } + private: Container::iterator m_begin; Container::iterator m_end; diff --git a/source/code.cpp b/source/code.cpp index 14f603c..8e3bd6c 100644 --- a/source/code.cpp +++ b/source/code.cpp @@ -134,18 +134,17 @@ std::string newTempFileName() bool codeExecuteCommand(const std::string& command, const std::string& file) { bool success = system(command.c_str()) == 0; - if (success) { - if (std::ifstream output (file); output.good()) { - std::ostringstream sstr; - sstr << output.rdbuf(); - log(sstr.str().c_str()); - } else { - log("Could not read command output!"); - } - - std::filesystem::remove(file); + + if (std::ifstream output (file); output.good()) { + std::ostringstream sstr; + sstr << output.rdbuf(); + log(sstr.str().c_str()); + } else { + log("Could not read command output!"); } + std::filesystem::remove(file); + return success; } diff --git a/source/device.cpp b/source/device.cpp index 11e181e..60b1bc9 100644 --- a/source/device.cpp +++ b/source/device.cpp @@ -33,6 +33,7 @@ extern void log(const std::string& str); extern std::vector deviceGenLoadFormulaEval(const std::string&); extern std::ifstream compileOpenBinaryFile(); +extern void deviceRenderDisconnect(); std::shared_ptr m_device; @@ -45,9 +46,15 @@ static std::deque drawSamplesInputQueue; static bool drawSamplesInput = false; static unsigned int drawSamplesBufferSize = 1; +bool deviceConnect(); + void deviceSetInputDrawing(bool enabled) { drawSamplesInput = enabled; + if (enabled) { + drawSamplesQueue.clear(); + drawSamplesInputQueue.clear(); + } } static void measureCodeTask(std::shared_ptr device) @@ -55,7 +62,7 @@ static void measureCodeTask(std::shared_ptr device) std::this_thread::sleep_for(std::chrono::seconds(1)); if (device) { - const auto cycles = device->continuous_start_get_measurement(); + const auto cycles = device->measurement_read(); log(std::string("Execution time: ") + std::to_string(cycles) + " cycles."); } } @@ -109,11 +116,21 @@ static void drawSamplesTask(std::shared_ptr device) const auto next = std::chrono::high_resolution_clock::now() + bufferTime; if (lockDevice.try_lock_until(next)) { - const auto chunk = tryReceiveChunk(device, + std::vector chunk, chunk2; + + chunk = tryReceiveChunk(device, std::mem_fn(&stmdsp::device::continuous_read)); + if (drawSamplesInput) { + chunk2 = tryReceiveChunk(device, + std::mem_fn(&stmdsp::device::continuous_read_input)); + } + lockDevice.unlock(); addToQueue(drawSamplesQueue, chunk); + if (drawSamplesInput) + addToQueue(drawSamplesInputQueue, chunk2); + if (logSamplesFile.is_open()) { for (const auto& s : chunk) logSamplesFile << s << '\n'; @@ -123,16 +140,6 @@ static void drawSamplesTask(std::shared_ptr device) std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - if (drawSamplesInput) { - if (lockDevice.try_lock_for(std::chrono::milliseconds(1))) { - const auto chunk2 = tryReceiveChunk(device, - std::mem_fn(&stmdsp::device::continuous_read_input)); - lockDevice.unlock(); - - addToQueue(drawSamplesInputQueue, chunk2); - } - } - std::this_thread::sleep_until(next); } } @@ -193,6 +200,12 @@ static void statusTask(std::shared_ptr device) case stmdsp::Error::ConversionAborted: log("Error: Algorithm unloaded, a fault occurred!"); break; + case stmdsp::Error::GUIDisconnect: + // Do GUI events for disconnect if device was lost. + deviceConnect(); + deviceRenderDisconnect(); + return; + break; default: log("Error: Device had an issue..."); break; @@ -301,7 +314,7 @@ bool deviceConnect() return false; } -void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples) +void deviceStart(bool logResults, bool drawSamples) { if (!m_device) { log("No device connected."); @@ -320,18 +333,22 @@ void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples) } log("Ready."); } else { - if (measureCodeTime) { - m_device->continuous_start_measure(); - std::thread(measureCodeTask, m_device).detach(); - } else { - m_device->continuous_start(); - if (drawSamples || logResults || wavOutput.valid()) - std::thread(drawSamplesTask, m_device).detach(); - } + m_device->continuous_start(); + if (drawSamples || logResults || wavOutput.valid()) + std::thread(drawSamplesTask, m_device).detach(); + log("Running."); } } +void deviceStartMeasurement() +{ + if (m_device && m_device->is_running()) { + m_device->measurement_start(); + std::thread(measureCodeTask, m_device).detach(); + } +} + void deviceAlgorithmUpload() { if (!m_device) { @@ -387,7 +404,7 @@ void deviceGenLoadList(const std::string_view list) } } - it = itend; + it = std::find_if(itend, list.cend(), isdigit); } if (it == list.cend()) { diff --git a/source/gui_device.cpp b/source/gui_device.cpp index 43c0a58..f846414 100644 --- a/source/gui_device.cpp +++ b/source/gui_device.cpp @@ -24,7 +24,8 @@ void deviceLoadAudioFile(const std::string& file); void deviceLoadLogFile(const std::string& file); void deviceSetSampleRate(unsigned int index); void deviceSetInputDrawing(bool enabled); -void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples); +void deviceStart(bool logResults, bool drawSamples); +void deviceStartMeasurement(); void deviceUpdateDrawBufferSize(double timeframe); std::size_t pullFromDrawQueue( CircularBuffer& circ, @@ -47,6 +48,15 @@ static std::string getSampleRatePreview(unsigned int rate) return std::to_string(rate / 1000) + " kHz"; } +static std::string connectLabel ("Connect"); +void deviceRenderDisconnect() +{ + connectLabel = "Connect"; + measureCodeTime = false; + logResults = false; + drawSamples = false; +} + void deviceRenderMenu() { auto addMenuItem = [](const std::string& label, bool enable, auto action) { @@ -56,7 +66,6 @@ void deviceRenderMenu() }; if (ImGui::BeginMenu("Device")) { - static std::string connectLabel ("Connect"); addMenuItem(connectLabel, !m_device || !m_device->is_running(), [&] { if (deviceConnect()) { connectLabel = "Disconnect"; @@ -64,10 +73,7 @@ void deviceRenderMenu() getSampleRatePreview(m_device->get_sample_rate()); deviceUpdateDrawBufferSize(drawSamplesTimeframe); } else { - connectLabel = "Connect"; - measureCodeTime = false; - logResults = false; - drawSamples = false; + deviceRenderDisconnect(); } }); @@ -79,7 +85,7 @@ void deviceRenderMenu() static std::string startLabel ("Start"); addMenuItem(startLabel, isConnected, [&] { startLabel = isRunning ? "Start" : "Stop"; - deviceStart(measureCodeTime, logResults, drawSamples); + deviceStart(logResults, drawSamples); if (logResults && isRunning) logResults = false; }); @@ -87,28 +93,25 @@ void deviceRenderMenu() deviceAlgorithmUpload); addMenuItem("Unload algorithm", isConnected && !isRunning, deviceAlgorithmUnload); + addMenuItem("Measure Code Time", isRunning, deviceStartMeasurement); ImGui::Separator(); if (!isConnected || isRunning) - ImGui::PushDisabled(); + ImGui::PushDisabled(); // Hey, pushing disabled! - ImGui::Checkbox("Measure Code Time", &measureCodeTime); ImGui::Checkbox("Draw samples", &drawSamples); if (ImGui::Checkbox("Log results...", &logResults)) { if (logResults) popupRequestLog = true; } + addMenuItem("Set buffer size...", true, [] { popupRequestBuffer = true; }); if (!isConnected || isRunning) ImGui::PopDisabled(); - - addMenuItem("Set buffer size...", isConnected && !isRunning, - [] { popupRequestBuffer = true; }); - ImGui::Separator(); addMenuItem("Load signal generator", - isConnected && !m_device->is_siggening(), + isConnected && !m_device->is_siggening() && !m_device->is_running(), [] { popupRequestSiggen = true; }); static std::string startSiggenLabel ("Start signal generator"); @@ -193,7 +196,7 @@ void deviceRenderWidgets() } } else { ImGui::Text(siggenOption == 0 ? "Enter a list of numbers:" - : "Enter a formula. f(x) = "); + : "Enter a formula. x = sample #, y = -1 to 1.\nf(x) = "); ImGui::PushStyleColor(ImGuiCol_FrameBg, {.8, .8, .8, 1}); ImGui::InputText("", siggenInput.data(), siggenInput.size()); ImGui::PopStyleColor(); @@ -286,8 +289,13 @@ void deviceRenderDraw() ImGui::Begin("draw", &drawSamples); ImGui::Text("Draw input "); ImGui::SameLine(); - if (ImGui::Checkbox("", &drawSamplesInput)) + if (ImGui::Checkbox("", &drawSamplesInput)) { deviceSetInputDrawing(drawSamplesInput); + if (drawSamplesInput) { + bufferCirc.reset(2048); + bufferInputCirc.reset(2048); + } + } ImGui::SameLine(); ImGui::Text("Time: %0.3f sec", drawSamplesTimeframe); ImGui::SameLine(); diff --git a/source/stmdsp/stmdsp.cpp b/source/stmdsp/stmdsp.cpp index 2252364..d7e977b 100644 --- a/source/stmdsp/stmdsp.cpp +++ b/source/stmdsp/stmdsp.cpp @@ -90,8 +90,7 @@ namespace stmdsp m_serial->write(cmd.data(), cmd.size()); success = true; } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } @@ -108,8 +107,7 @@ namespace stmdsp m_serial->read(dest, dest_size); success = true; } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } @@ -158,12 +156,11 @@ namespace stmdsp m_is_running = true; } - void device::continuous_start_measure() { - if (try_command({'M'})) - m_is_running = true; + void device::measurement_start() { + try_command({'M'}); } - uint32_t device::continuous_start_get_measurement() { + uint32_t device::measurement_read() { uint32_t count = 0; try_read({'m'}, reinterpret_cast(&count), sizeof(uint32_t)); return count / 2; @@ -193,8 +190,7 @@ namespace stmdsp } } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } @@ -225,8 +221,7 @@ namespace stmdsp } } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } @@ -251,8 +246,7 @@ namespace stmdsp m_serial->write(request, 3); m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t)); } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } else { try { @@ -262,8 +256,7 @@ namespace stmdsp else m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t)); } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } @@ -295,8 +288,7 @@ namespace stmdsp m_serial->write(request, 3); m_serial->write(buffer, size); } catch (...) { - m_serial.release(); - log("Lost connection!"); + handle_disconnect(); } } } @@ -318,9 +310,19 @@ namespace stmdsp bool running = ret.first == RunStatus::Running; if (m_is_running != running) m_is_running = running; + } else if (m_disconnect_error_flag) { + m_disconnect_error_flag = false; + return {RunStatus::Idle, Error::GUIDisconnect}; } return ret; } -} + + void device::handle_disconnect() + { + m_disconnect_error_flag = true; + m_serial.release(); + log("Lost connection!"); + } +} // namespace stmdsp diff --git a/source/stmdsp/stmdsp.hpp b/source/stmdsp/stmdsp.hpp index e0fca90..efed8a3 100644 --- a/source/stmdsp/stmdsp.hpp +++ b/source/stmdsp/stmdsp.hpp @@ -63,12 +63,15 @@ namespace stmdsp */ enum class Error : char { None = 0, - BadParam, /* An invalid parameter was passed for a command. */ - BadParamSize, /* An invaild param. size was given for a command. */ - BadUserCodeLoad, /* Device failed to load the given algorithm. */ - BadUserCodeSize, /* The given algorithm is too large for the device. */ - NotIdle, /* An idle-only command was received while not Idle. */ - ConversionAborted /* A conversion was aborted due to a fault. */ + BadParam, /* An invalid parameter was passed for a command. */ + BadParamSize, /* An invaild param. size was given for a command. */ + BadUserCodeLoad, /* Device failed to load the given algorithm. */ + BadUserCodeSize, /* The given algorithm is too large for the device. */ + NotIdle, /* An idle-only command was received while not Idle. */ + ConversionAborted, /* A conversion was aborted due to a fault. */ + NotRunning, /* A running-only command was received while not Running. */ + + GUIDisconnect = 100 /* The GUI lost connection with the device. */ }; /** @@ -123,8 +126,8 @@ namespace stmdsp void continuous_start(); void continuous_stop(); - void continuous_start_measure(); - uint32_t continuous_start_get_measurement(); + void measurement_start(); + uint32_t measurement_read(); std::vector continuous_read(); std::vector continuous_read_input(); @@ -149,11 +152,13 @@ namespace stmdsp unsigned int m_sample_rate = 0; bool m_is_siggening = false; bool m_is_running = false; + bool m_disconnect_error_flag = false; std::mutex m_lock; bool try_command(std::basic_string data); bool try_read(std::basic_string cmd, uint8_t *dest, unsigned int dest_size); + void handle_disconnect(); }; }