diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/Makefile | 17 | ||||
-rw-r--r-- | gui/stmdsp.cpp | 27 | ||||
-rw-r--r-- | gui/stmdsp.hpp | 3 | ||||
-rw-r--r-- | gui/wxmain.cpp | 91 | ||||
-rw-r--r-- | gui/wxmain.hpp | 6 |
5 files changed, 128 insertions, 16 deletions
diff --git a/gui/Makefile b/gui/Makefile index 679e1e4..20dd473 100644 --- a/gui/Makefile +++ b/gui/Makefile @@ -1,18 +1,21 @@ CXX = g++-10 -CXXFLAGS = --std=c++20 -ggdb -Og \ - -Wall -Wextra -pedantic \ - -Wno-deprecated-copy \ - -Iserial/include \ - $(shell wx-config --cxxflags) +CXXFLAGS = --std=c++20 -ggdb -O0 \ + -Wall -Wextra -pedantic \ + -Wno-deprecated-copy \ + -Iserial/include \ + $(shell wx-config --cxxflags) -CXXFILES = $(shell find serial/src -name "*.cc") $(wildcard *.cpp) +CXXFILES = serial/src/serial.cc \ + serial/src/impl/unix.cc \ + serial/src/impl/list_ports/list_ports_linux.cc \ + $(wildcard *.cpp) OFILES = $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES))) LIBS = $(shell wx-config --libs) -lwx_gtk3u_stc-3.1 OUTELF = stmdspgui all: $(OUTELF) - + $(OUTELF): $(OFILES) @echo " CXX " $(OUTELF) @$(CXX) $(CXXFLAGS) $(OFILES) $(LIBS) -o $(OUTELF) diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp index 1b4bba6..5ea18af 100644 --- a/gui/stmdsp.cpp +++ b/gui/stmdsp.cpp @@ -120,6 +120,33 @@ namespace stmdsp return {}; } + std::vector<adcsample_t> device::continuous_read_input() { + if (connected()) { + m_serial.write("t"); + unsigned char sizebytes[2]; + m_serial.read(sizebytes, 2); + unsigned int size = sizebytes[0] | (sizebytes[1] << 8); + if (size > 0) { + std::vector<adcsample_t> data (size); + unsigned int total = size * sizeof(adcsample_t); + unsigned int offset = 0; + + while (total > 512) { + m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512); + m_serial.write("n"); + offset += 512; + total -= 512; + } + m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total); + m_serial.write("n"); + return data; + + } + } + + return {}; + } + void device::continuous_stop() { if (connected()) m_serial.write("S"); diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp index f805ab3..a22a55d 100644 --- a/gui/stmdsp.hpp +++ b/gui/stmdsp.hpp @@ -19,7 +19,7 @@ namespace stmdsp { - constexpr unsigned int SAMPLES_MAX = 4000; + constexpr unsigned int SAMPLES_MAX = 4096; class scanner { @@ -62,6 +62,7 @@ namespace stmdsp void continuous_start_measure(); uint32_t continuous_start_get_measurement(); std::vector<adcsample_t> continuous_read(); + std::vector<adcsample_t> continuous_read_input(); void continuous_stop(); void siggen_upload(dacsample_t *buffer, unsigned int size); diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp index c7acddf..e5f0d4d 100644 --- a/gui/wxmain.cpp +++ b/gui/wxmain.cpp @@ -12,6 +12,7 @@ #include "wxmain.hpp" #include <wx/combobox.h> +#include <wx/dcclient.h> #include <wx/dir.h> #include <wx/filename.h> #include <wx/filedlg.h> @@ -25,6 +26,7 @@ #include <wx/textdlg.h> #include <array> +#include <sys/mman.h> #include <vector> static const std::array<wxString, 6> srateValues { @@ -133,6 +135,7 @@ enum Id { MRunConnect, MRunStart, MRunMeasure, + MRunDrawSamples, MRunLogResults, MRunUpload, MRunUnload, @@ -177,6 +180,12 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50) wxDefaultPosition, wxDefaultSize, srateValues.size(), srateValues.data(), wxCB_READONLY); + m_device_samples = reinterpret_cast<stmdsp::adcsample_t *>(::mmap( + nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); + m_device_samples_input = reinterpret_cast<stmdsp::adcsample_t *>(::mmap( + nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)); m_menu_bar->Append(menuFile, "&File"); m_menu_bar->Append(menuRun, "&Run"); @@ -217,6 +226,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50) // General Bind(wxEVT_TIMER, &MainFrame::onMeasureTimer, this, Id::MeasureTimer); Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY); + Bind(wxEVT_PAINT, &MainFrame::onPaint, this, wxID_ANY); // Toolbar actions Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, Id::MCodeCompile, wxID_ANY, comp); @@ -237,6 +247,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50) menuRun->AppendSeparator(); Bind(wxEVT_MENU, &MainFrame::onRunStart, this, Id::MRunStart, wxID_ANY, menuRun->Append(MRunStart, "&Start")); m_run_measure = menuRun->AppendCheckItem(MRunMeasure, "&Measure code time"); + m_run_draw_samples = menuRun->AppendCheckItem(MRunDrawSamples, "&Draw samples"); Bind(wxEVT_MENU, &MainFrame::onRunLogResults, this, Id::MRunLogResults, wxID_ANY, menuRun->AppendCheckItem(MRunLogResults, "&Log results...")); menuRun->AppendSeparator(); Bind(wxEVT_MENU, &MainFrame::onRunUpload, this, Id::MRunUpload, wxID_ANY, menuRun->Append(MRunUpload, "&Upload code")); @@ -276,12 +287,21 @@ void MainFrame::onCloseEvent(wxCloseEvent& event) // Only called while connected and running. void MainFrame::onMeasureTimer(wxTimerEvent&) { - if (m_conv_result_log) { - // We're meant to log - if (auto samples = m_device->continuous_read(); samples.size() > 0) { - for (auto& s : samples) { - auto str = std::to_string(s); - m_conv_result_log->Write(str.c_str(), str.size()); + if (m_conv_result_log || m_run_draw_samples->IsChecked()) { + auto samples = m_device->continuous_read(); + if (samples.size() > 0) { + std::copy(samples.cbegin(), samples.cend(), m_device_samples); + + if (m_conv_result_log) { + for (auto& s : samples) { + auto str = std::to_string(s); + m_conv_result_log->Write(str.c_str(), str.size()); + } + } + if (m_run_draw_samples->IsChecked()) { + samples = m_device->continuous_read_input(); + std::copy(samples.cbegin(), samples.cend(), m_device_samples_input); + this->Refresh(); } } } @@ -304,6 +324,54 @@ void MainFrame::onMeasureTimer(wxTimerEvent&) } } +void MainFrame::onPaint(wxPaintEvent&) +{ + if (!m_is_running || !m_run_draw_samples->IsChecked()) { + if (!m_compile_output->IsShown()) + m_compile_output->Show(); + return; + } else if (m_compile_output->IsShown()) { + m_compile_output->Hide(); + } + + auto py = m_compile_output->GetScreenPosition().y - this->GetScreenPosition().y - 28; + wxRect rect { + 0, py, + this->GetSize().GetWidth(), + this->GetSize().GetHeight() - py - 60 + }; + + auto *dc = new wxPaintDC(this); + dc->SetBrush(*wxBLACK_BRUSH); + dc->SetPen(*wxBLACK_PEN); + dc->DrawRectangle(rect); + dc->SetBrush(*wxRED_BRUSH); + dc->SetPen(*wxRED_PEN); + auto stoy = [&](stmdsp::adcsample_t s) { + return static_cast<float>(py) + rect.GetHeight() - + (static_cast<float>(rect.GetHeight()) * s / 4095.f); + }; + auto scount = m_device->get_buffer_size(); + float dx = static_cast<float>(rect.GetWidth()) / scount; + float x = 0; + float lasty = stoy(2048); + for (decltype(scount) i = 0; i < scount; i++) { + auto y = stoy(m_device_samples[i]); + dc->DrawLine(x, lasty, x + dx, y); + x += dx, lasty = y; + } + dc->SetBrush(*wxBLUE_BRUSH); + dc->SetPen(*wxBLUE_PEN); + x = 0; + lasty = stoy(2048); + for (decltype(scount) i = 0; i < scount; i++) { + auto y = stoy(m_device_samples_input[i]); + dc->DrawLine(x, lasty, x + dx, y); + x += dx, lasty = y; + } + delete dc; +} + void MainFrame::prepareEditor() { m_text_editor->SetLexer(wxSTC_LEX_CPP); @@ -536,11 +604,14 @@ void MainFrame::onRunStart(wxCommandEvent& ce) srateNums[m_rate_select->GetSelection()]); } else if (m_conv_result_log) { m_measure_timer->Start(15); + } else if (m_run_draw_samples->IsChecked()) { + m_measure_timer->Start(300); } m_device->continuous_start(); } + m_rate_select->Enable(false); menuItem->SetItemLabel("&Stop"); m_status_bar->SetStatusText("Running."); m_is_running = true; @@ -548,9 +619,13 @@ void MainFrame::onRunStart(wxCommandEvent& ce) m_device->continuous_stop(); m_measure_timer->Stop(); + m_rate_select->Enable(true); menuItem->SetItemLabel("&Start"); m_status_bar->SetStatusText("Ready."); m_is_running = false; + + if (m_run_draw_samples->IsChecked()) + m_compile_output->Refresh(); } } @@ -581,7 +656,7 @@ void MainFrame::onRunLogResults(wxCommandEvent& ce) void MainFrame::onRunEditBSize(wxCommandEvent&) { - wxTextEntryDialog dialog (this, "Enter new buffer size (100-4000)", "Set Buffer Size"); + wxTextEntryDialog dialog (this, "Enter new buffer size (100-4096)", "Set Buffer Size"); if (dialog.ShowModal() == wxID_OK) { if (wxString value = dialog.GetValue(); !value.IsEmpty()) { if (unsigned long n; value.ToULong(&n)) { @@ -667,9 +742,11 @@ void MainFrame::onRunGenStart(wxCommandEvent& ce) if (menuItem->IsChecked()) { m_device->siggen_start(); menuItem->SetItemLabel("Stop &generator"); + m_status_bar->SetStatusText("Generator running."); } else { m_device->siggen_stop(); menuItem->SetItemLabel("Start &generator"); + m_status_bar->SetStatusText("Ready."); } } diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp index e96f51d..9b3db1e 100644 --- a/gui/wxmain.hpp +++ b/gui/wxmain.hpp @@ -58,7 +58,8 @@ public: void onRunCompile(wxCommandEvent&); void onCodeDisassemble(wxCommandEvent&); - void onMeasureTimer(wxTimerEvent& te); + void onPaint(wxPaintEvent&); + void onMeasureTimer(wxTimerEvent&); private: // Set to true if connected and running @@ -69,6 +70,7 @@ private: wxTextCtrl *m_compile_output = nullptr; wxControl *m_signal_area = nullptr; wxMenuItem *m_run_measure = nullptr; + wxMenuItem *m_run_draw_samples = nullptr; wxTimer *m_measure_timer = nullptr; wxStatusBar *m_status_bar = nullptr; wxMenuBar *m_menu_bar = nullptr; @@ -87,6 +89,8 @@ private: // Device interface // Not null if connected stmdsp::device *m_device = nullptr; + stmdsp::adcsample_t *m_device_samples = nullptr; + stmdsp::adcsample_t *m_device_samples_input = nullptr; // WAV data for signal generator // Not null when a WAV is loaded wav::clip *m_wav_clip = nullptr; |