diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp index 5fca940..06f0100 100644 --- a/gui/stmdsp.cpp +++ b/gui/stmdsp.cpp @@ -46,6 +46,21 @@ namespace stmdsp m_serial.write("R"); } + void device::continuous_start_measure() { + if (connected()) + m_serial.write("M"); + } + + uint32_t device::continuous_start_get_measurement() { + uint32_t count = 0; + if (connected()) { + m_serial.write("m"); + m_serial.read(reinterpret_cast(&count), sizeof(uint32_t)); + } + + return count; + } + std::vector device::continuous_read() { if (connected()) { m_serial.write("s"); diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp index ec58e5a..2820ea4 100644 --- a/gui/stmdsp.hpp +++ b/gui/stmdsp.hpp @@ -41,6 +41,8 @@ namespace stmdsp std::vector sample(unsigned long int count = 1); void continuous_start(); + void continuous_start_measure(); + uint32_t continuous_start_get_measurement(); std::vector continuous_read(); void continuous_stop(); diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp index 277f369..2d38fad 100644 --- a/gui/wxmain.cpp +++ b/gui/wxmain.cpp @@ -1,10 +1,15 @@ #include "wxmain.hpp" #include +#include #include MainFrame::MainFrame() : wxFrame(nullptr, -1, "Hello world", wxPoint(50, 50), wxSize(640, 800)) { + auto menubar = new wxMenuBar; + auto menuFile = new wxMenu; + menubar->Append(menuFile, "&File"); + SetMenuBar(menubar); auto window = new wxBoxSizer(wxVERTICAL); @@ -95,7 +100,7 @@ void MainFrame::onSinglePressed(wxCommandEvent& ce) if (!m_render_timer->IsRunning()) { if (m_device != nullptr && m_device->connected()) { - m_device->continuous_start(); + m_device->continuous_start_measure(); m_device_samples_future = std::async(std::launch::async, []() { return decltype(m_device_samples)(); }); m_render_timer->Start(1000); @@ -108,7 +113,8 @@ void MainFrame::onSinglePressed(wxCommandEvent& ce) //m_device_samples.clear(); //this->RefreshRect(m_signal_area->GetRect()); - button->SetLabel("Run"); + //button->SetLabel("Run"); + button->SetLabel(wxString::Format(wxT("%u"), m_device->continuous_start_get_measurement())); } } @@ -199,7 +205,7 @@ all: $0.o )make"; -static const char *file_header = R"cpp( +static wxString file_header (R"cpp( #include using adcsample_t = uint16_t; @@ -213,26 +219,29 @@ extern "C" void process_data_entry() // End stmdspgui header code -)cpp"; +)cpp"); wxString MainFrame::compileEditorCode() { - auto file_text = wxString(file_header) + m_text_editor->GetText(); - auto file_name = wxFileName::CreateTempFileName("stmdspgui"); - wxFile file (file_name, wxFile::write); - file.Write(file_text); + static wxString temp_file_name; + + if (temp_file_name.IsEmpty()) + temp_file_name = wxFileName::CreateTempFileName("stmdspgui"); + + wxFile file (temp_file_name, wxFile::write); + file.Write(file_header + m_text_editor->GetText()); file.Close(); - wxFile makefile (file_name + "make", wxFile::write); + wxFile makefile (temp_file_name + "make", wxFile::write); wxString make_text (makefile_text); - make_text.Replace("$0", file_name); + make_text.Replace("$0", temp_file_name); makefile.Write(make_text); makefile.Close(); - wxString make_command = wxString("make -C ") + file_name.BeforeLast('/') + - " -f " + file_name + "make"; + wxString make_command = wxString("make -C ") + temp_file_name.BeforeLast('/') + + " -f " + temp_file_name + "make"; if (system(make_command.ToAscii()) == 0) - return file_name + ".o"; + return temp_file_name + ".o"; else return ""; } diff --git a/source/adc.cpp b/source/adc.cpp index eca0d16..c28c38f 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -79,6 +79,11 @@ namespace adc adcStartConversion(adcd, &adc_group_config, buffer, count); gptStartContinuous(gptd, 5); } + + void read_set_operation_func(operation_t operation_func) + { + adc_operation_func = operation_func; + } void read_stop() { diff --git a/source/adc.hpp b/source/adc.hpp index 376b156..d1cd292 100644 --- a/source/adc.hpp +++ b/source/adc.hpp @@ -32,6 +32,7 @@ namespace adc void init(); adcsample_t *read(adcsample_t *buffer, size_t count); void read_start(operation_t operation_func, adcsample_t *buffer, size_t count); + void read_set_operation_func(operation_t operation_func); void read_stop(); void set_rate(rate r); } diff --git a/source/main.cpp b/source/main.cpp index 043353d..c0f0651 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -29,8 +29,10 @@ enum class RunStatus : char }; static RunStatus run_status = RunStatus::Idle; -#define MSG_CONVFIRST (1) -#define MSG_CONVSECOND (2) +#define MSG_CONVFIRST (1) +#define MSG_CONVSECOND (2) +#define MSG_CONVFIRST_MEASURE (3) +#define MSG_CONVSECOND_MEASURE (4) static msg_t conversionMBBuffer[8]; static MAILBOX_DECL(conversionMB, conversionMBBuffer, 8); @@ -38,6 +40,8 @@ static MAILBOX_DECL(conversionMB, conversionMBBuffer, 8); static THD_WORKING_AREA(conversionThreadWA, 1024); static THD_FUNCTION(conversionThread, arg); +static time_measurement_t conversion_time_measurement; + static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); @@ -54,6 +58,7 @@ static uint8_t elf_file_store[8192]; static elf::entry_t elf_entry = nullptr; static void signal_operate(adcsample_t *buffer, size_t count); +static void signal_operate_measure(adcsample_t *buffer, size_t count); static void main_loop(); int main() @@ -74,6 +79,7 @@ int main() usbserial::init(); // Start the conversion manager thread + chTMObjectInit(&conversion_time_measurement); chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA), NORMALPRIO, conversionThread, nullptr); @@ -115,6 +121,21 @@ void main_loop() dac::write_start(&dac_samples[0], dac_samples.size()); break; + // 'M' - Begins continuous sampling, but measures the execution time of the first + // sample processing. This duration can be later read through 'm'. + case 'M': + run_status = RunStatus::Converting; + dac_samples.fill(0); + adc::read_start(signal_operate_measure, &adc_samples[0], adc_samples.size()); + dac::write_start(&dac_samples[0], dac_samples.size()); + break; + + // 'm' - Returns the last measured sample processing time, presumably in processor + // ticks. + case 'm': + usbserial::write(&conversion_time_measurement.last, sizeof(rtcnt_t)); + break; + // 's' - Sends the current contents of the DAC buffer back over USB. case 's': usbserial::write(dac_samples.data(), 1/*dac_samples.size()*/ * sizeof(dacsample_t)); @@ -216,6 +237,22 @@ THD_FUNCTION(conversionThread, arg) if (!samples) samples = &adc_samples[adc_samples.size() / 2]; std::copy(samples, samples + halfsize, &dac_samples[dac_samples.size() / 2]); + } else if (message == MSG_CONVFIRST_MEASURE) { + chTMStartMeasurementX(&conversion_time_measurement); + if (elf_entry) + samples = elf_entry(&adc_samples[adc_samples.size() / 2], halfsize); + chTMStopMeasurementX(&conversion_time_measurement); + if (!samples) + samples = &adc_samples[adc_samples.size() / 2]; + std::copy(samples, samples + halfsize, &dac_samples[dac_samples.size() / 2]); + } else if (message == MSG_CONVSECOND_MEASURE) { + chTMStartMeasurementX(&conversion_time_measurement); + if (elf_entry) + samples = elf_entry(&adc_samples[adc_samples.size() / 2], halfsize); + chTMStopMeasurementX(&conversion_time_measurement); + if (!samples) + samples = &adc_samples[adc_samples.size() / 2]; + std::copy(samples, samples + halfsize, &dac_samples[dac_samples.size() / 2]); } } } @@ -229,6 +266,12 @@ void signal_operate(adcsample_t *buffer, [[maybe_unused]] size_t count) chMBPostI(&conversionMB, buffer == &adc_samples[0] ? MSG_CONVFIRST : MSG_CONVSECOND); } +void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count) +{ + chMBPostI(&conversionMB, buffer == &adc_samples[0] ? MSG_CONVFIRST_MEASURE : MSG_CONVSECOND_MEASURE); + adc::read_set_operation_func(signal_operate); +} + extern "C" { __attribute__((naked))