bug fixes; dynamic time measure; sync sample drawing

pull/1/head
Clyne 3 years ago
parent 1b176cf6cd
commit 660d967ec0
Signed by: clyne
GPG Key ID: 3267C8EBF3F9AFC7

@ -21,7 +21,7 @@ public:
CircularBuffer(Container<T>& container) : CircularBuffer(Container<T>& container) :
m_begin(std::begin(container)), m_begin(std::begin(container)),
m_end(std::end(container)), m_end(std::end(container)),
m_current(std::begin(container)) {} m_current(m_begin) {}
void put(const T& value) noexcept { void put(const T& value) noexcept {
*m_current = value; *m_current = value;
@ -33,6 +33,11 @@ public:
return std::distance(m_begin, m_end); 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: private:
Container<T>::iterator m_begin; Container<T>::iterator m_begin;
Container<T>::iterator m_end; Container<T>::iterator m_end;

@ -134,18 +134,17 @@ std::string newTempFileName()
bool codeExecuteCommand(const std::string& command, const std::string& file) bool codeExecuteCommand(const std::string& command, const std::string& file)
{ {
bool success = system(command.c_str()) == 0; bool success = system(command.c_str()) == 0;
if (success) {
if (std::ifstream output (file); output.good()) { if (std::ifstream output (file); output.good()) {
std::ostringstream sstr; std::ostringstream sstr;
sstr << output.rdbuf(); sstr << output.rdbuf();
log(sstr.str().c_str()); log(sstr.str().c_str());
} else { } else {
log("Could not read command output!"); log("Could not read command output!");
}
std::filesystem::remove(file);
} }
std::filesystem::remove(file);
return success; return success;
} }

@ -33,6 +33,7 @@
extern void log(const std::string& str); extern void log(const std::string& str);
extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&); extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&);
extern std::ifstream compileOpenBinaryFile(); extern std::ifstream compileOpenBinaryFile();
extern void deviceRenderDisconnect();
std::shared_ptr<stmdsp::device> m_device; std::shared_ptr<stmdsp::device> m_device;
@ -45,9 +46,15 @@ static std::deque<stmdsp::dacsample_t> drawSamplesInputQueue;
static bool drawSamplesInput = false; static bool drawSamplesInput = false;
static unsigned int drawSamplesBufferSize = 1; static unsigned int drawSamplesBufferSize = 1;
bool deviceConnect();
void deviceSetInputDrawing(bool enabled) void deviceSetInputDrawing(bool enabled)
{ {
drawSamplesInput = enabled; drawSamplesInput = enabled;
if (enabled) {
drawSamplesQueue.clear();
drawSamplesInputQueue.clear();
}
} }
static void measureCodeTask(std::shared_ptr<stmdsp::device> device) static void measureCodeTask(std::shared_ptr<stmdsp::device> device)
@ -55,7 +62,7 @@ static void measureCodeTask(std::shared_ptr<stmdsp::device> device)
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
if (device) { 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."); log(std::string("Execution time: ") + std::to_string(cycles) + " cycles.");
} }
} }
@ -109,11 +116,21 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
const auto next = std::chrono::high_resolution_clock::now() + bufferTime; const auto next = std::chrono::high_resolution_clock::now() + bufferTime;
if (lockDevice.try_lock_until(next)) { if (lockDevice.try_lock_until(next)) {
const auto chunk = tryReceiveChunk(device, std::vector<stmdsp::dacsample_t> chunk, chunk2;
chunk = tryReceiveChunk(device,
std::mem_fn(&stmdsp::device::continuous_read)); std::mem_fn(&stmdsp::device::continuous_read));
if (drawSamplesInput) {
chunk2 = tryReceiveChunk(device,
std::mem_fn(&stmdsp::device::continuous_read_input));
}
lockDevice.unlock(); lockDevice.unlock();
addToQueue(drawSamplesQueue, chunk); addToQueue(drawSamplesQueue, chunk);
if (drawSamplesInput)
addToQueue(drawSamplesInputQueue, chunk2);
if (logSamplesFile.is_open()) { if (logSamplesFile.is_open()) {
for (const auto& s : chunk) for (const auto& s : chunk)
logSamplesFile << s << '\n'; logSamplesFile << s << '\n';
@ -123,16 +140,6 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
std::this_thread::sleep_for(std::chrono::milliseconds(500)); 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); std::this_thread::sleep_until(next);
} }
} }
@ -193,6 +200,12 @@ static void statusTask(std::shared_ptr<stmdsp::device> device)
case stmdsp::Error::ConversionAborted: case stmdsp::Error::ConversionAborted:
log("Error: Algorithm unloaded, a fault occurred!"); log("Error: Algorithm unloaded, a fault occurred!");
break; break;
case stmdsp::Error::GUIDisconnect:
// Do GUI events for disconnect if device was lost.
deviceConnect();
deviceRenderDisconnect();
return;
break;
default: default:
log("Error: Device had an issue..."); log("Error: Device had an issue...");
break; break;
@ -301,7 +314,7 @@ bool deviceConnect()
return false; return false;
} }
void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples) void deviceStart(bool logResults, bool drawSamples)
{ {
if (!m_device) { if (!m_device) {
log("No device connected."); log("No device connected.");
@ -320,18 +333,22 @@ void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples)
} }
log("Ready."); log("Ready.");
} else { } else {
if (measureCodeTime) { m_device->continuous_start();
m_device->continuous_start_measure(); if (drawSamples || logResults || wavOutput.valid())
std::thread(measureCodeTask, m_device).detach(); std::thread(drawSamplesTask, m_device).detach();
} else {
m_device->continuous_start();
if (drawSamples || logResults || wavOutput.valid())
std::thread(drawSamplesTask, m_device).detach();
}
log("Running."); log("Running.");
} }
} }
void deviceStartMeasurement()
{
if (m_device && m_device->is_running()) {
m_device->measurement_start();
std::thread(measureCodeTask, m_device).detach();
}
}
void deviceAlgorithmUpload() void deviceAlgorithmUpload()
{ {
if (!m_device) { 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()) { if (it == list.cend()) {

@ -24,7 +24,8 @@ void deviceLoadAudioFile(const std::string& file);
void deviceLoadLogFile(const std::string& file); void deviceLoadLogFile(const std::string& file);
void deviceSetSampleRate(unsigned int index); void deviceSetSampleRate(unsigned int index);
void deviceSetInputDrawing(bool enabled); void deviceSetInputDrawing(bool enabled);
void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples); void deviceStart(bool logResults, bool drawSamples);
void deviceStartMeasurement();
void deviceUpdateDrawBufferSize(double timeframe); void deviceUpdateDrawBufferSize(double timeframe);
std::size_t pullFromDrawQueue( std::size_t pullFromDrawQueue(
CircularBuffer<std::vector, stmdsp::dacsample_t>& circ, CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
@ -47,6 +48,15 @@ static std::string getSampleRatePreview(unsigned int rate)
return std::to_string(rate / 1000) + " kHz"; return std::to_string(rate / 1000) + " kHz";
} }
static std::string connectLabel ("Connect");
void deviceRenderDisconnect()
{
connectLabel = "Connect";
measureCodeTime = false;
logResults = false;
drawSamples = false;
}
void deviceRenderMenu() void deviceRenderMenu()
{ {
auto addMenuItem = [](const std::string& label, bool enable, auto action) { auto addMenuItem = [](const std::string& label, bool enable, auto action) {
@ -56,7 +66,6 @@ void deviceRenderMenu()
}; };
if (ImGui::BeginMenu("Device")) { if (ImGui::BeginMenu("Device")) {
static std::string connectLabel ("Connect");
addMenuItem(connectLabel, !m_device || !m_device->is_running(), [&] { addMenuItem(connectLabel, !m_device || !m_device->is_running(), [&] {
if (deviceConnect()) { if (deviceConnect()) {
connectLabel = "Disconnect"; connectLabel = "Disconnect";
@ -64,10 +73,7 @@ void deviceRenderMenu()
getSampleRatePreview(m_device->get_sample_rate()); getSampleRatePreview(m_device->get_sample_rate());
deviceUpdateDrawBufferSize(drawSamplesTimeframe); deviceUpdateDrawBufferSize(drawSamplesTimeframe);
} else { } else {
connectLabel = "Connect"; deviceRenderDisconnect();
measureCodeTime = false;
logResults = false;
drawSamples = false;
} }
}); });
@ -79,7 +85,7 @@ void deviceRenderMenu()
static std::string startLabel ("Start"); static std::string startLabel ("Start");
addMenuItem(startLabel, isConnected, [&] { addMenuItem(startLabel, isConnected, [&] {
startLabel = isRunning ? "Start" : "Stop"; startLabel = isRunning ? "Start" : "Stop";
deviceStart(measureCodeTime, logResults, drawSamples); deviceStart(logResults, drawSamples);
if (logResults && isRunning) if (logResults && isRunning)
logResults = false; logResults = false;
}); });
@ -87,28 +93,25 @@ void deviceRenderMenu()
deviceAlgorithmUpload); deviceAlgorithmUpload);
addMenuItem("Unload algorithm", isConnected && !isRunning, addMenuItem("Unload algorithm", isConnected && !isRunning,
deviceAlgorithmUnload); deviceAlgorithmUnload);
addMenuItem("Measure Code Time", isRunning, deviceStartMeasurement);
ImGui::Separator(); ImGui::Separator();
if (!isConnected || isRunning) if (!isConnected || isRunning)
ImGui::PushDisabled(); ImGui::PushDisabled(); // Hey, pushing disabled!
ImGui::Checkbox("Measure Code Time", &measureCodeTime);
ImGui::Checkbox("Draw samples", &drawSamples); ImGui::Checkbox("Draw samples", &drawSamples);
if (ImGui::Checkbox("Log results...", &logResults)) { if (ImGui::Checkbox("Log results...", &logResults)) {
if (logResults) if (logResults)
popupRequestLog = true; popupRequestLog = true;
} }
addMenuItem("Set buffer size...", true, [] { popupRequestBuffer = true; });
if (!isConnected || isRunning) if (!isConnected || isRunning)
ImGui::PopDisabled(); ImGui::PopDisabled();
addMenuItem("Set buffer size...", isConnected && !isRunning,
[] { popupRequestBuffer = true; });
ImGui::Separator(); ImGui::Separator();
addMenuItem("Load signal generator", addMenuItem("Load signal generator",
isConnected && !m_device->is_siggening(), isConnected && !m_device->is_siggening() && !m_device->is_running(),
[] { popupRequestSiggen = true; }); [] { popupRequestSiggen = true; });
static std::string startSiggenLabel ("Start signal generator"); static std::string startSiggenLabel ("Start signal generator");
@ -193,7 +196,7 @@ void deviceRenderWidgets()
} }
} else { } else {
ImGui::Text(siggenOption == 0 ? "Enter a list of numbers:" 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::PushStyleColor(ImGuiCol_FrameBg, {.8, .8, .8, 1});
ImGui::InputText("", siggenInput.data(), siggenInput.size()); ImGui::InputText("", siggenInput.data(), siggenInput.size());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
@ -286,8 +289,13 @@ void deviceRenderDraw()
ImGui::Begin("draw", &drawSamples); ImGui::Begin("draw", &drawSamples);
ImGui::Text("Draw input "); ImGui::Text("Draw input ");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox("", &drawSamplesInput)) if (ImGui::Checkbox("", &drawSamplesInput)) {
deviceSetInputDrawing(drawSamplesInput); deviceSetInputDrawing(drawSamplesInput);
if (drawSamplesInput) {
bufferCirc.reset(2048);
bufferInputCirc.reset(2048);
}
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("Time: %0.3f sec", drawSamplesTimeframe); ImGui::Text("Time: %0.3f sec", drawSamplesTimeframe);
ImGui::SameLine(); ImGui::SameLine();

@ -90,8 +90,7 @@ namespace stmdsp
m_serial->write(cmd.data(), cmd.size()); m_serial->write(cmd.data(), cmd.size());
success = true; success = true;
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
@ -108,8 +107,7 @@ namespace stmdsp
m_serial->read(dest, dest_size); m_serial->read(dest, dest_size);
success = true; success = true;
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
@ -158,12 +156,11 @@ namespace stmdsp
m_is_running = true; m_is_running = true;
} }
void device::continuous_start_measure() { void device::measurement_start() {
if (try_command({'M'})) try_command({'M'});
m_is_running = true;
} }
uint32_t device::continuous_start_get_measurement() { uint32_t device::measurement_read() {
uint32_t count = 0; uint32_t count = 0;
try_read({'m'}, reinterpret_cast<uint8_t *>(&count), sizeof(uint32_t)); try_read({'m'}, reinterpret_cast<uint8_t *>(&count), sizeof(uint32_t));
return count / 2; return count / 2;
@ -193,8 +190,7 @@ namespace stmdsp
} }
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
@ -225,8 +221,7 @@ namespace stmdsp
} }
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
@ -251,8 +246,7 @@ namespace stmdsp
m_serial->write(request, 3); m_serial->write(request, 3);
m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t)); m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t));
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} else { } else {
try { try {
@ -262,8 +256,7 @@ namespace stmdsp
else else
m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t)); m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t));
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
@ -295,8 +288,7 @@ namespace stmdsp
m_serial->write(request, 3); m_serial->write(request, 3);
m_serial->write(buffer, size); m_serial->write(buffer, size);
} catch (...) { } catch (...) {
m_serial.release(); handle_disconnect();
log("Lost connection!");
} }
} }
} }
@ -318,9 +310,19 @@ namespace stmdsp
bool running = ret.first == RunStatus::Running; bool running = ret.first == RunStatus::Running;
if (m_is_running != running) if (m_is_running != running)
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; return ret;
} }
}
void device::handle_disconnect()
{
m_disconnect_error_flag = true;
m_serial.release();
log("Lost connection!");
}
} // namespace stmdsp

@ -63,12 +63,15 @@ namespace stmdsp
*/ */
enum class Error : char { enum class Error : char {
None = 0, None = 0,
BadParam, /* An invalid parameter was passed for a command. */ BadParam, /* An invalid parameter was passed for a command. */
BadParamSize, /* An invaild param. size was given for a command. */ BadParamSize, /* An invaild param. size was given for a command. */
BadUserCodeLoad, /* Device failed to load the given algorithm. */ BadUserCodeLoad, /* Device failed to load the given algorithm. */
BadUserCodeSize, /* The given algorithm is too large for the device. */ BadUserCodeSize, /* The given algorithm is too large for the device. */
NotIdle, /* An idle-only command was received while not Idle. */ NotIdle, /* An idle-only command was received while not Idle. */
ConversionAborted /* A conversion was aborted due to a fault. */ 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_start();
void continuous_stop(); void continuous_stop();
void continuous_start_measure(); void measurement_start();
uint32_t continuous_start_get_measurement(); uint32_t measurement_read();
std::vector<adcsample_t> continuous_read(); std::vector<adcsample_t> continuous_read();
std::vector<adcsample_t> continuous_read_input(); std::vector<adcsample_t> continuous_read_input();
@ -149,11 +152,13 @@ namespace stmdsp
unsigned int m_sample_rate = 0; unsigned int m_sample_rate = 0;
bool m_is_siggening = false; bool m_is_siggening = false;
bool m_is_running = false; bool m_is_running = false;
bool m_disconnect_error_flag = false;
std::mutex m_lock; std::mutex m_lock;
bool try_command(std::basic_string<uint8_t> data); bool try_command(std::basic_string<uint8_t> data);
bool try_read(std::basic_string<uint8_t> cmd, uint8_t *dest, unsigned int dest_size); bool try_read(std::basic_string<uint8_t> cmd, uint8_t *dest, unsigned int dest_size);
void handle_disconnect();
}; };
} }

Loading…
Cancel
Save