bug fixes; dynamic time measure; sync sample drawing

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

@ -21,7 +21,7 @@ public:
CircularBuffer(Container<T>& 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<T>::iterator m_begin;
Container<T>::iterator m_end;

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

@ -33,6 +33,7 @@
extern void log(const std::string& str);
extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&);
extern std::ifstream compileOpenBinaryFile();
extern void deviceRenderDisconnect();
std::shared_ptr<stmdsp::device> m_device;
@ -45,9 +46,15 @@ static std::deque<stmdsp::dacsample_t> 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<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));
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<stmdsp::device> device)
const auto next = std::chrono::high_resolution_clock::now() + bufferTime;
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));
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<stmdsp::device> 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<stmdsp::device> 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()) {

@ -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<std::vector, stmdsp::dacsample_t>& 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();

@ -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<uint8_t *>(&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

@ -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<adcsample_t> continuous_read();
std::vector<adcsample_t> 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<uint8_t> data);
bool try_read(std::basic_string<uint8_t> cmd, uint8_t *dest, unsigned int dest_size);
void handle_disconnect();
};
}

Loading…
Cancel
Save